**/\r
\r
#include "FmpDxe.h"\r
+#include "VariableSupport.h"\r
\r
///\r
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the\r
NULL, // VersionName\r
TRUE, // RuntimeVersionSupported\r
NULL, // FmpDeviceLockEvent\r
- FALSE // FmpDeviceLocked\r
+ FALSE, // FmpDeviceLocked\r
+ NULL, // FmpDeviceContext\r
+ NULL, // VersionVariableName\r
+ NULL, // LsvVariableName\r
+ NULL, // LastAttemptStatusVariableName\r
+ NULL, // LastAttemptVersionVariableName\r
+ NULL // FmpStateVariableName\r
};\r
\r
///\r
the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide\r
a GUID value, then gEfiCallerIdGuid is returned.\r
\r
- @return The ImageTypeId GUID\r
+ @retval The ImageTypeId GUID\r
\r
**/\r
EFI_GUID *\r
/**\r
Returns a pointer to the Null-terminated Unicode ImageIdName string.\r
\r
- @return Null-terminated Unicode ImageIdName string.\r
+ @retval Null-terminated Unicode ImageIdName string.\r
\r
**/\r
CHAR16 *\r
2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)\r
3. Check Fixed at build PCD\r
\r
- @return The largest value\r
+ @param[in] Private Pointer to the private context structure for the\r
+ Firmware Management Protocol instance.\r
+\r
+ @retval The largest value\r
\r
**/\r
UINT32\r
GetLowestSupportedVersion (\r
- VOID\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
EFI_STATUS Status;\r
//\r
// Check the lowest supported version UEFI variable for this device\r
//\r
- VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable();\r
+ VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);\r
if (VariableLowestSupportedVersion > ReturnLsv) {\r
ReturnLsv = VariableLowestSupportedVersion;\r
}\r
Private->Descriptor.ImageId = Private->Descriptor.ImageIndex;\r
Private->Descriptor.ImageIdName = GetImageTypeNameString();\r
\r
+ //\r
+ // Get the hardware instance from FmpDeviceLib\r
+ //\r
+ Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);\r
+ if (Status == EFI_UNSUPPORTED) {\r
+ Private->Descriptor.HardwareInstance = 0;\r
+ }\r
+\r
+ //\r
+ // Generate UEFI Variable names used to store status information for this\r
+ // FMP instance.\r
+ //\r
+ GenerateFmpVariableNames (Private);\r
+\r
//\r
// Get the version. Some devices don't support getting the firmware version\r
// at runtime. If FmpDeviceLib does not support returning a version, then\r
Status = FmpDeviceGetVersion (&Private->Descriptor.Version);\r
if (Status == EFI_UNSUPPORTED) {\r
Private->RuntimeVersionSupported = FALSE;\r
- Private->Descriptor.Version = GetVersionFromVariable();\r
+ Private->Descriptor.Version = GetVersionFromVariable (Private);\r
} else if (EFI_ERROR (Status)) {\r
//\r
// Unexpected error. Use default version.\r
);\r
}\r
\r
- Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion();\r
+ Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);\r
\r
//\r
// Get attributes from the FmpDeviceLib\r
Private->Descriptor.Size = 0;\r
}\r
\r
- Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable ();\r
- Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable ();\r
-\r
- //\r
- // Get the hardware instance from FmpDeviceLib\r
- //\r
- Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);\r
- if (Status == EFI_UNSUPPORTED) {\r
- Private->Descriptor.HardwareInstance = 0;\r
- }\r
+ Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);\r
+ Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);\r
\r
Private->DescriptorPopulated = TRUE;\r
}\r
*ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);\r
\r
//\r
- // make sure the descriptor has already been loaded\r
+ // Make sure the descriptor has already been loaded or refreshed\r
//\r
PopulateDescriptor (Private);\r
\r
FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
\r
//\r
- // make sure the descriptor has already been loaded\r
+ // Make sure the descriptor has already been loaded or refreshed\r
//\r
PopulateDescriptor (Private);\r
\r
Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);\r
FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);\r
\r
- SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.\r
+ //\r
+ // Make sure the descriptor has already been loaded or refreshed\r
+ //\r
+ PopulateDescriptor (Private);\r
+\r
+ //\r
+ // Set to 0 to clear any previous results.\r
+ //\r
+ SetLastAttemptVersionInVariable (Private, IncommingFwVersion);\r
\r
//\r
// if we have locked the device, then skip the set operation.\r
//\r
// Set to actual value\r
//\r
- SetLastAttemptVersionInVariable (IncommingFwVersion);\r
+ SetLastAttemptVersionInVariable (Private, IncommingFwVersion);\r
}\r
\r
\r
// Save LastAttemptStatus as error so that if SetImage never returns the error\r
// state is recorded.\r
//\r
- SetLastAttemptStatusInVariable (LastAttemptStatus);\r
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
\r
//\r
// Strip off all the headers so the device can process its firmware\r
if (!Private->RuntimeVersionSupported) {\r
Version = DEFAULT_VERSION;\r
GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);\r
- SetVersionInVariable (Version);\r
+ SetVersionInVariable (Private, Version);\r
}\r
\r
//\r
// Update lowest supported variable\r
//\r
- {\r
- LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
- GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
- SetLowestSupportedVersionInVariable (LowestSupportedVersion);\r
- }\r
+ LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;\r
+ GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);\r
+ SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);\r
\r
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
\r
cleanup:\r
mProgressFunc = NULL;\r
- SetLastAttemptStatusInVariable (LastAttemptStatus);\r
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);\r
\r
if (Progress != NULL) {\r
//\r
goto cleanup;\r
}\r
\r
+ //\r
+ // Make sure the descriptor has already been loaded or refreshed\r
+ //\r
+ PopulateDescriptor (Private);\r
+\r
DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Lock events\n"));\r
\r
if (IsLockFmpDeviceAtLockEventGuidRequired ()) {\r
//\r
// Lock all UEFI Variables used by this module.\r
//\r
- Status = LockAllFmpVariables ();\r
+ Status = LockAllFmpVariables (Private);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables. Status = %r.\n", Status));\r
} else {\r
if (Private->FmpDeviceLockEvent != NULL) {\r
gBS->CloseEvent (Private->FmpDeviceLockEvent);\r
}\r
+ if (Private->Descriptor.VersionName != NULL) {\r
+ FreePool (Private->Descriptor.VersionName);\r
+ }\r
+ if (Private->FmpDeviceContext != NULL) {\r
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
+ }\r
+ if (Private->VersionVariableName != NULL) {\r
+ FreePool (Private->VersionVariableName);\r
+ }\r
+ if (Private->LsvVariableName != NULL) {\r
+ FreePool (Private->LsvVariableName);\r
+ }\r
+ if (Private->LastAttemptStatusVariableName != NULL) {\r
+ FreePool (Private->LastAttemptStatusVariableName);\r
+ }\r
+ if (Private->LastAttemptVersionVariableName != NULL) {\r
+ FreePool (Private->LastAttemptVersionVariableName);\r
+ }\r
+ if (Private->FmpStateVariableName != NULL) {\r
+ FreePool (Private->FmpStateVariableName);\r
+ }\r
FreePool (Private);\r
}\r
}\r
return Status;\r
}\r
\r
- FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
-\r
+ if (Private->Descriptor.VersionName != NULL) {\r
+ FreePool (Private->Descriptor.VersionName);\r
+ }\r
+ if (Private->FmpDeviceContext != NULL) {\r
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);\r
+ }\r
+ if (Private->VersionVariableName != NULL) {\r
+ FreePool (Private->VersionVariableName);\r
+ }\r
+ if (Private->LsvVariableName != NULL) {\r
+ FreePool (Private->LsvVariableName);\r
+ }\r
+ if (Private->LastAttemptStatusVariableName != NULL) {\r
+ FreePool (Private->LastAttemptStatusVariableName);\r
+ }\r
+ if (Private->LastAttemptVersionVariableName != NULL) {\r
+ FreePool (Private->LastAttemptVersionVariableName);\r
+ }\r
+ if (Private->FmpStateVariableName != NULL) {\r
+ FreePool (Private->FmpStateVariableName);\r
+ }\r
FreePool (Private);\r
\r
return EFI_SUCCESS;\r
firmware updates.\r
\r
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
-#include <PiDxe.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-#include <Library/UefiLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Protocol/VariableLock.h>\r
+#include "FmpDxe.h"\r
#include "VariableSupport.h"\r
\r
-///\r
-/// Array of UEFI variable names that are locked in LockAllFmpVariables().\r
-///\r
-const CHAR16 *mFmpVariableLockList[] = {\r
- VARNAME_VERSION,\r
- VARNAME_LSV,\r
- VARNAME_LASTATTEMPTSTATUS,\r
- VARNAME_LASTATTEMPTVERSION\r
-};\r
+/**\r
+ Retrieve the value of a 32-bit UEFI Variable specified by VariableName and\r
+ a GUID of gEfiCallerIdGuid.\r
+\r
+ @param[in] VariableName Pointer to the UEFI Variable name to retrieve.\r
+ @param[out] Valid Set to TRUE if UEFI Variable is present and the size\r
+ of the UEFI Variable value is 32-bits. Otherwise\r
+ FALSE.\r
+ @param[out] Value If Valid is set to TRUE, then the 32-bit value of\r
+ the UEFI Variable. Otherwise 0.\r
+**/\r
+static\r
+VOID\r
+GetFmpVariable (\r
+ IN CHAR16 *VariableName,\r
+ OUT BOOLEAN *Valid,\r
+ OUT UINT32 *Value\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Size;\r
+ UINT32 *Buffer;\r
+\r
+ *Valid = FALSE;\r
+ *Value = 0;\r
+ Size = 0;\r
+ Buffer = NULL;\r
+ Status = GetVariable2 (\r
+ VariableName,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **)&Buffer,\r
+ &Size\r
+ );\r
+ if (!EFI_ERROR (Status) && Size == sizeof (*Value) && Buffer != NULL) {\r
+ *Valid = TRUE;\r
+ *Value = *Buffer;\r
+ }\r
+ if (Buffer != NULL) {\r
+ FreePool (Buffer);\r
+ }\r
+}\r
\r
/**\r
- Returns the value used to fill in the Version field of the\r
- EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r
- service of the Firmware Management Protocol. The value is read from a UEFI\r
- variable. If the UEFI variables does not exist, then a default version value\r
- is returned.\r
+ Delete the UEFI Variable with name specified by VariableName and GUID of\r
+ gEfiCallerIdGuid. If the variable can not be deleted, then print a\r
+ DEBUG_ERROR message.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"\r
+ @param[in] VariableName Pointer to the UEFI Variable name to delete.\r
+**/\r
+static\r
+VOID\r
+DeleteFmpVariable (\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ BOOLEAN Valid;\r
+ UINT32 Value;\r
\r
- @return The version of the firmware image in the firmware device.\r
+ GetFmpVariable (VariableName, &Valid, &Value);\r
+ if (Valid) {\r
+ Status = gRT->SetVariable (VariableName, &gEfiCallerIdGuid, 0, 0, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to delete FMP Variable %s. Status = %r\n", VariableName, Status));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "Deleted FMP Variable %s\n", VariableName));\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Retrieve the FMP Controller State UEFI Variable value. Return NULL if\r
+ the variable does not exist or if the size of the UEFI Variable is not the\r
+ size of FMP_CONTROLLER_STATE. The buffer for the UEFI Variable value\r
+ if allocated using the UEFI Boot Service AllocatePool().\r
\r
+ @param[in] Private Private context structure for the managed controller.\r
+\r
+ @return Pointer to the allocated FMP Controller State. Returns NULL\r
+ if the variable does not exist or is a different size than expected.\r
**/\r
-UINT32\r
-GetVersionFromVariable (\r
- VOID\r
+static\r
+FMP_CONTROLLER_STATE *\r
+GetFmpControllerState (\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 *Value;\r
- UINTN Size;\r
- UINT32 Version;\r
+ EFI_STATUS Status;\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ UINTN Size;\r
+\r
+ FmpControllerState = NULL;\r
+ Size = 0;\r
+ Status = GetVariable2 (\r
+ Private->FmpStateVariableName,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **)&FmpControllerState,\r
+ &Size\r
+ );\r
+ if (EFI_ERROR (Status) || FmpControllerState == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to get the FMP Controller State. Status = %r\n", Status));\r
+ } else {\r
+ if (Size == sizeof (*FmpControllerState)) {\r
+ return FmpControllerState;\r
+ }\r
+ DEBUG ((DEBUG_ERROR, "Getting FMP Controller State returned a size different than expected. Size = 0x%x\n", Size));\r
+ }\r
+ if (FmpControllerState != NULL) {\r
+ FreePool (FmpControllerState);\r
+ }\r
+ return NULL;\r
+}\r
\r
- Value = NULL;\r
- Size = 0;\r
- Version = DEFAULT_VERSION;\r
+/**\r
+ Generates a Null-terminated Unicode string UEFI Variable name from a base name\r
+ and a hardware instance. If the hardware instance value is 0, then the base\r
+ name is returned. If the hardware instance value is non-zero, then the 64-bit\r
+ hardware instance value is converted to a 16 character hex string and appended\r
+ to base name. The UEFI Variable name returned is allocated using the UEFI\r
+ Boot Service AllocatePool().\r
+\r
+ @param[in] HardwareInstance 64-bit hardware instance value.\r
+ @param[in] BaseVariableName Null-terminated Unicode string that is the base\r
+ name of the UEFI Variable.\r
+\r
+ @return Pointer to the allocated UEFI Variable name. Returns NULL if the\r
+ UEFI Variable can not be allocated.\r
+**/\r
+static\r
+CHAR16 *\r
+GenerateFmpVariableName (\r
+ IN UINT64 HardwareInstance,\r
+ IN CHAR16 *BaseVariableName\r
+ )\r
+{\r
+ CHAR16 *VariableName;\r
+\r
+ VariableName = CatSPrint (NULL, BaseVariableName);\r
+ if (VariableName == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to generate FMP variable name %s.\n", BaseVariableName));\r
+ return VariableName;\r
+ }\r
+ if (HardwareInstance == 0) {\r
+ return VariableName;\r
+ }\r
+ VariableName = CatSPrint (VariableName, L"%016lx", HardwareInstance);\r
+ if (VariableName == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Failed to generate FMP variable name %s.\n", BaseVariableName));\r
+ }\r
+ return VariableName;\r
+}\r
+\r
+/**\r
+ Generate the names of the UEFI Variables used to store state information for\r
+ a managed controller. The UEFI Variables names are a combination of a base\r
+ name and an optional hardware instance value as a 16 character hex value. If\r
+ the hardware instance value is 0, then the 16 character hex value is not\r
+ included. These storage for the UEFI Variable names are allocated using the\r
+ UEFI Boot Service AllocatePool() and the pointers are stored in the Private.\r
+ The following are examples of variable names produces for hardware instance\r
+ value 0 and value 0x1234567812345678.\r
+\r
+ FmpVersion\r
+ FmpLsv\r
+ LastAttemptStatus\r
+ LastAttemptVersion\r
+ FmpState\r
+\r
+ FmpVersion1234567812345678\r
+ FmpLsv1234567812345678\r
+ LastAttemptStatus1234567812345678\r
+ LastAttemptVersion1234567812345678\r
+ FmpState1234567812345678\r
+\r
+ @param[in,out] Private Private context structure for the managed controller.\r
+**/\r
+VOID\r
+GenerateFmpVariableNames (\r
+ IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *Buffer;\r
+ FMP_CONTROLLER_STATE FmpControllerState;\r
+\r
+ if (Private->VersionVariableName != NULL) {\r
+ FreePool (Private->VersionVariableName);\r
+ }\r
+ if (Private->LsvVariableName != NULL) {\r
+ FreePool (Private->LsvVariableName);\r
+ }\r
+ if (Private->LastAttemptStatusVariableName != NULL) {\r
+ FreePool (Private->LastAttemptStatusVariableName);\r
+ }\r
+ if (Private->LastAttemptVersionVariableName != NULL) {\r
+ FreePool (Private->LastAttemptVersionVariableName);\r
+ }\r
+ if (Private->FmpStateVariableName != NULL) {\r
+ FreePool (Private->FmpStateVariableName);\r
+ }\r
\r
- Status = GetVariable2 (VARNAME_VERSION, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
- if (EFI_ERROR (Status) || (Value == NULL)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to get the Version from variable. Status = %r\n", Status));\r
- return Version;\r
+ Private->VersionVariableName = GenerateFmpVariableName (\r
+ Private->Descriptor.HardwareInstance,\r
+ VARNAME_VERSION\r
+ );\r
+ Private->LsvVariableName = GenerateFmpVariableName (\r
+ Private->Descriptor.HardwareInstance,\r
+ VARNAME_LSV\r
+ );\r
+ Private->LastAttemptStatusVariableName = GenerateFmpVariableName (\r
+ Private->Descriptor.HardwareInstance,\r
+ VARNAME_LASTATTEMPTSTATUS\r
+ );\r
+ Private->LastAttemptVersionVariableName = GenerateFmpVariableName (\r
+ Private->Descriptor.HardwareInstance,\r
+ VARNAME_LASTATTEMPTVERSION\r
+ );\r
+ Private->FmpStateVariableName = GenerateFmpVariableName (\r
+ Private->Descriptor.HardwareInstance,\r
+ VARNAME_FMPSTATE\r
+ );\r
+\r
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->VersionVariableName));\r
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LsvVariableName));\r
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LastAttemptStatusVariableName));\r
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->LastAttemptVersionVariableName));\r
+ DEBUG ((DEBUG_INFO, "FmpDxe Variable %g %s\n", &gEfiCallerIdGuid, Private->FmpStateVariableName));\r
+\r
+ Buffer = GetFmpControllerState (Private);\r
+ if (Buffer != NULL) {\r
+ //\r
+ // FMP Controller State was found with correct size.\r
+ // Delete old variables if they exist.\r
+ //\r
+ FreePool (Buffer);\r
+ DeleteFmpVariable (Private->VersionVariableName);\r
+ DeleteFmpVariable (Private->LsvVariableName);\r
+ DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r
+ DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r
+ return;\r
}\r
\r
//\r
- // No error from call\r
+ // FMP Controller State was either not found or is wrong size.\r
+ // Create a new FMP Controller State variable with the correct size.\r
//\r
- if (Size == sizeof (*Value)) {\r
+ DEBUG ((DEBUG_INFO, "Create FMP Controller State\n"));\r
+ GetFmpVariable (\r
+ Private->VersionVariableName,\r
+ &FmpControllerState.VersionValid,\r
+ &FmpControllerState.Version\r
+ );\r
+ GetFmpVariable (\r
+ Private->LsvVariableName,\r
+ &FmpControllerState.LsvValid,\r
+ &FmpControllerState.Lsv\r
+ );\r
+ GetFmpVariable (\r
+ Private->LastAttemptStatusVariableName,\r
+ &FmpControllerState.LastAttemptStatusValid,\r
+ &FmpControllerState.LastAttemptStatus\r
+ );\r
+ GetFmpVariable (\r
+ Private->LastAttemptVersionVariableName,\r
+ &FmpControllerState.LastAttemptVersionValid,\r
+ &FmpControllerState.LastAttemptVersion\r
+ );\r
+ Status = gRT->SetVariable (\r
+ Private->FmpStateVariableName,\r
+ &gEfiCallerIdGuid,\r
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
+ sizeof (FmpControllerState),\r
+ &FmpControllerState\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
//\r
- // Successful read\r
+ // Failed to create FMP Controller State. In this case, do not\r
+ // delete the individual variables. They can be used again on next boot\r
+ // to create the FMP Controller State.\r
//\r
- Version = *Value;\r
+ DEBUG ((DEBUG_ERROR, "Failed to create FMP Controller State. Status = %r\n", Status));\r
} else {\r
- //\r
- // Return default since size was unknown\r
- //\r
- DEBUG ((DEBUG_ERROR, "Getting version Variable returned a size different than expected. Size = 0x%x\n", Size));\r
+ DeleteFmpVariable (Private->VersionVariableName);\r
+ DeleteFmpVariable (Private->LsvVariableName);\r
+ DeleteFmpVariable (Private->LastAttemptStatusVariableName);\r
+ DeleteFmpVariable (Private->LastAttemptVersionVariableName);\r
}\r
+}\r
\r
- FreePool (Value);\r
+/**\r
+ Returns the value used to fill in the Version field of the\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r
+ service of the Firmware Management Protocol. The value is read from a UEFI\r
+ variable. If the UEFI variables does not exist, then a default version value\r
+ is returned.\r
+\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
\r
- return Version;\r
+ @param[in] Private Private context structure for the managed controller.\r
+\r
+ @return The version of the firmware image in the firmware device.\r
+**/\r
+UINT32\r
+GetVersionFromVariable (\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ UINT32 Value;\r
+\r
+ Value = DEFAULT_VERSION;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState != NULL) {\r
+ if (FmpControllerState->VersionValid) {\r
+ Value = FmpControllerState->Version;\r
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s Version %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ Value\r
+ ));\r
+ }\r
+ FreePool (FmpControllerState);\r
+ }\r
+ return Value;\r
}\r
\r
/**\r
variable. If the UEFI variables does not exist, then a default lowest\r
supported version value is returned.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
+\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
@return The lowest supported version of the firmware image in the firmware\r
device.\r
-\r
**/\r
UINT32\r
GetLowestSupportedVersionFromVariable (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 *Value;\r
- UINTN Size;\r
- UINT32 Version;\r
-\r
- Value = NULL;\r
- Size = 0;\r
- Version = DEFAULT_LOWESTSUPPORTEDVERSION;\r
-\r
- Status = GetVariable2 (VARNAME_LSV, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
- if (EFI_ERROR (Status) || (Value == NULL)) {\r
- DEBUG ((DEBUG_WARN, "Warning: Failed to get the Lowest Supported Version from variable. Status = %r\n", Status));\r
- return Version;\r
- }\r
-\r
- //\r
- // No error from call\r
- //\r
- if (Size == sizeof (*Value)) {\r
- //\r
- // Successful read\r
- //\r
- Version = *Value;\r
- } else {\r
- //\r
- // Return default since size was unknown\r
- //\r
- DEBUG ((DEBUG_ERROR, "Getting LSV Variable returned a size different than expected. Size = 0x%x\n", Size));\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ UINT32 Value;\r
+\r
+ Value = DEFAULT_LOWESTSUPPORTEDVERSION;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState != NULL) {\r
+ if (FmpControllerState->LsvValid) {\r
+ Value = FmpControllerState->Lsv;\r
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LowestSupportedVersion %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ Value\r
+ ));\r
+ }\r
+ FreePool (FmpControllerState);\r
}\r
-\r
- FreePool (Value);\r
-\r
- return Version;\r
+ return Value;\r
}\r
\r
/**\r
variable. If the UEFI variables does not exist, then a default last attempt\r
status value is returned.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
\r
- @return The last attempt status value for the most recent capsule update.\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
+ @return The last attempt status value for the most recent capsule update.\r
**/\r
UINT32\r
GetLastAttemptStatusFromVariable (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 *Value;\r
- UINTN Size;\r
- UINT32 LastAttemptStatus;\r
-\r
- Value = NULL;\r
- Size = 0;\r
- LastAttemptStatus = DEFAULT_LASTATTEMPT;\r
-\r
- Status = GetVariable2 (VARNAME_LASTATTEMPTSTATUS, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
- if (EFI_ERROR (Status) || (Value == NULL)) {\r
- DEBUG ((DEBUG_WARN, "Warning: Failed to get the Last Attempt Status from variable. Status = %r\n", Status));\r
- return LastAttemptStatus;\r
- }\r
-\r
- //\r
- // No error from call\r
- //\r
- if (Size == sizeof (*Value)) {\r
- //\r
- // Successful read\r
- //\r
- LastAttemptStatus = *Value;\r
- } else {\r
- //\r
- // Return default since size was unknown\r
- //\r
- DEBUG (\r
- (DEBUG_ERROR,\r
- "Getting Last Attempt Status Variable returned a size different than expected. Size = 0x%x\n",\r
- Size)\r
- );\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ UINT32 Value;\r
+\r
+ Value = DEFAULT_LASTATTEMPTSTATUS;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState != NULL) {\r
+ if (FmpControllerState->LastAttemptStatusValid) {\r
+ Value = FmpControllerState->LastAttemptStatus;\r
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LastAttemptStatus %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ Value\r
+ ));\r
+ }\r
+ FreePool (FmpControllerState);\r
}\r
-\r
- FreePool (Value);\r
-\r
- return LastAttemptStatus;\r
+ return Value;\r
}\r
\r
/**\r
variable. If the UEFI variables does not exist, then a default last attempt\r
version value is returned.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
\r
- @return The last attempt version value for the most recent capsule update.\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
+ @return The last attempt version value for the most recent capsule update.\r
**/\r
UINT32\r
GetLastAttemptVersionFromVariable (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 *Value;\r
- UINTN Size;\r
- UINT32 Version;\r
-\r
- Value = NULL;\r
- Size = 0;\r
- Version = DEFAULT_LASTATTEMPT;\r
-\r
- Status = GetVariable2 (VARNAME_LASTATTEMPTVERSION, &gEfiCallerIdGuid, (VOID **)&Value, &Size);\r
- if (EFI_ERROR (Status) || (Value == NULL)) {\r
- DEBUG ((DEBUG_WARN, "Warning: Failed to get the Last Attempt Version from variable. Status = %r\n", Status));\r
- return Version;\r
- }\r
-\r
- //\r
- // No error from call\r
- //\r
- if (Size == sizeof (*Value)) {\r
- //\r
- // Successful read\r
- //\r
- Version = *Value;\r
- } else {\r
- //\r
- // Return default since size was unknown\r
- //\r
- DEBUG (\r
- (DEBUG_ERROR,\r
- "Getting Last Attempt Version variable returned a size different than expected. Size = 0x%x\n",\r
- Size)\r
- );\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ UINT32 Value;\r
+\r
+ Value = DEFAULT_LASTATTEMPTVERSION;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState != NULL) {\r
+ if (FmpControllerState->LastAttemptVersionValid) {\r
+ Value = FmpControllerState->LastAttemptVersion;\r
+ DEBUG ((DEBUG_INFO, "Get FMP Variable %g %s LastAttemptVersion %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ Value\r
+ ));\r
+ }\r
+ FreePool (FmpControllerState);\r
}\r
-\r
- FreePool (Value);\r
-\r
- return Version;\r
+ return Value;\r
}\r
\r
-\r
/**\r
Saves the version current of the firmware image in the firmware device to a\r
UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
\r
+ @param[in] Private Private context structure for the managed controller.\r
@param[in] Version The version of the firmware image in the firmware device.\r
-\r
**/\r
VOID\r
SetVersionInVariable (\r
- UINT32 Version\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 Version\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 Current;\r
+ EFI_STATUS Status;\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ BOOLEAN Update;\r
\r
- Status = EFI_SUCCESS;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState == NULL) {\r
+ //\r
+ // Can not update value if FMP Controller State does not exist.\r
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+ //\r
+ return;\r
+ }\r
\r
- Current = GetVersionFromVariable();\r
- if (Current != Version) {\r
+ Update = FALSE;\r
+ if (!FmpControllerState->VersionValid) {\r
+ Update = TRUE;\r
+ }\r
+ if (FmpControllerState->Version != Version) {\r
+ Update = TRUE;\r
+ }\r
+ if (!Update) {\r
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));\r
+ } else {\r
+ FmpControllerState->VersionValid = TRUE;\r
+ FmpControllerState->Version = Version;\r
Status = gRT->SetVariable (\r
- VARNAME_VERSION,\r
+ Private->FmpStateVariableName,\r
&gEfiCallerIdGuid,\r
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- sizeof (Version),\r
- &Version\r
+ sizeof (*FmpControllerState),\r
+ FmpControllerState\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to set the Version into a variable. Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s Version %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ Version\r
+ ));\r
}\r
- } else {\r
- DEBUG ((DEBUG_INFO, "Version variable doesn't need to update. Same value as before.\n"));\r
}\r
+ FreePool (FmpControllerState);\r
}\r
\r
/**\r
Saves the lowest supported version current of the firmware image in the\r
firmware device to a UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"\r
-\r
- @param[in] LowestSupportedVersion The lowest supported version of the firmware image\r
- in the firmware device.\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
\r
+ @param[in] Private Private context structure for the managed\r
+ controller.\r
+ @param[in] LowestSupportedVersion The lowest supported version of the\r
+ firmware image in the firmware device.\r
**/\r
VOID\r
SetLowestSupportedVersionInVariable (\r
- UINT32 LowestSupportedVersion\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 LowestSupportedVersion\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 Current;\r
+ EFI_STATUS Status;\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ BOOLEAN Update;\r
\r
- Status = EFI_SUCCESS;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState == NULL) {\r
+ //\r
+ // Can not update value if FMP Controller State does not exist.\r
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+ //\r
+ return;\r
+ }\r
\r
- Current = GetLowestSupportedVersionFromVariable();\r
- if (LowestSupportedVersion > Current) {\r
+ Update = FALSE;\r
+ if (!FmpControllerState->LsvValid) {\r
+ Update = TRUE;\r
+ }\r
+ if (FmpControllerState->Lsv < LowestSupportedVersion) {\r
+ Update = TRUE;\r
+ }\r
+ if (!Update) {\r
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));\r
+ } else {\r
+ FmpControllerState->LsvValid = TRUE;\r
+ FmpControllerState->Lsv = LowestSupportedVersion;\r
Status = gRT->SetVariable (\r
- VARNAME_LSV,\r
+ Private->FmpStateVariableName,\r
&gEfiCallerIdGuid,\r
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- sizeof (LowestSupportedVersion), &LowestSupportedVersion\r
+ sizeof (*FmpControllerState),\r
+ FmpControllerState\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to set the LSV into a variable. Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LowestSupportedVersion %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ LowestSupportedVersion\r
+ ));\r
}\r
- } else {\r
- DEBUG ((DEBUG_INFO, "LSV variable doesn't need to update. Same value as before.\n"));\r
}\r
+ FreePool (FmpControllerState);\r
}\r
\r
/**\r
Saves the last attempt status value of the most recent FMP capsule update to a\r
UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
\r
+ @param[in] Private Private context structure for the managed\r
+ controller.\r
@param[in] LastAttemptStatus The last attempt status of the most recent FMP\r
capsule update.\r
-\r
**/\r
VOID\r
SetLastAttemptStatusInVariable (\r
- UINT32 LastAttemptStatus\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 LastAttemptStatus\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 Current;\r
+ EFI_STATUS Status;\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ BOOLEAN Update;\r
\r
- Status = EFI_SUCCESS;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState == NULL) {\r
+ //\r
+ // Can not update value if FMP Controller State does not exist.\r
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+ //\r
+ return;\r
+ }\r
\r
- Current = GetLastAttemptStatusFromVariable();\r
- if (Current != LastAttemptStatus) {\r
+ Update = FALSE;\r
+ if (!FmpControllerState->LastAttemptStatusValid) {\r
+ Update = TRUE;\r
+ }\r
+ if (FmpControllerState->LastAttemptStatus != LastAttemptStatus) {\r
+ Update = TRUE;\r
+ }\r
+ if (!Update) {\r
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));\r
+ } else {\r
+ FmpControllerState->LastAttemptStatusValid = TRUE;\r
+ FmpControllerState->LastAttemptStatus = LastAttemptStatus;\r
Status = gRT->SetVariable (\r
- VARNAME_LASTATTEMPTSTATUS,\r
+ Private->FmpStateVariableName,\r
&gEfiCallerIdGuid,\r
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- sizeof (LastAttemptStatus),\r
- &LastAttemptStatus\r
+ sizeof (*FmpControllerState),\r
+ FmpControllerState\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to set the LastAttemptStatus into a variable. Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LastAttemptStatus %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ LastAttemptStatus\r
+ ));\r
}\r
- } else {\r
- DEBUG ((DEBUG_INFO, "LastAttemptStatus variable doesn't need to update. Same value as before.\n"));\r
}\r
+ FreePool (FmpControllerState);\r
}\r
\r
/**\r
Saves the last attempt version value of the most recent FMP capsule update to\r
a UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpState"\r
\r
+ @param[in] Private Private context structure for the managed\r
+ controller.\r
@param[in] LastAttemptVersion The last attempt version value of the most\r
recent FMP capsule update.\r
-\r
**/\r
VOID\r
SetLastAttemptVersionInVariable (\r
- UINT32 LastAttemptVersion\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 LastAttemptVersion\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT32 Current;\r
+ EFI_STATUS Status;\r
+ FMP_CONTROLLER_STATE *FmpControllerState;\r
+ BOOLEAN Update;\r
\r
- Status = EFI_SUCCESS;\r
+ FmpControllerState = GetFmpControllerState (Private);\r
+ if (FmpControllerState == NULL) {\r
+ //\r
+ // Can not update value if FMP Controller State does not exist.\r
+ // This variable is guaranteed to be created by GenerateFmpVariableNames().\r
+ //\r
+ return;\r
+ }\r
\r
- Current = GetLastAttemptVersionFromVariable();\r
- if (Current != LastAttemptVersion) {\r
+ Update = FALSE;\r
+ if (!FmpControllerState->LastAttemptVersionValid) {\r
+ Update = TRUE;\r
+ }\r
+ if (FmpControllerState->LastAttemptVersion != LastAttemptVersion) {\r
+ Update = TRUE;\r
+ }\r
+ if (!Update) {\r
+ DEBUG ((DEBUG_INFO, "No need to update FMP Controller State. Same value as before.\n"));\r
+ } else {\r
+ FmpControllerState->LastAttemptVersionValid = TRUE;\r
+ FmpControllerState->LastAttemptVersion = LastAttemptVersion;\r
Status = gRT->SetVariable (\r
- VARNAME_LASTATTEMPTVERSION,\r
+ Private->FmpStateVariableName,\r
&gEfiCallerIdGuid,\r
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
- sizeof (LastAttemptVersion),\r
- &LastAttemptVersion\r
+ sizeof (*FmpControllerState),\r
+ FmpControllerState\r
);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "Failed to set the LastAttemptVersion into a variable. Status = %r\n", Status));\r
+ DEBUG ((DEBUG_ERROR, "Failed to update FMP Controller State. Status = %r\n", Status));\r
+ } else {\r
+ DEBUG ((DEBUG_INFO, "Set FMP Variable %g %s LastAttemptVersion %08x\n",\r
+ &gEfiCallerIdGuid,\r
+ Private->FmpStateVariableName,\r
+ LastAttemptVersion\r
+ ));\r
}\r
- } else {\r
- DEBUG ((DEBUG_INFO, "LastAttemptVersion variable doesn't need to update. Same value as before.\n"));\r
}\r
+ FreePool (FmpControllerState);\r
}\r
\r
/**\r
- Locks all the UEFI Variables used by this module.\r
+ Attempts to lock a single UEFI Variable propagating the error state of the\r
+ first lock attempt that fails. Uses gEfiCallerIdGuid as the variable GUID.\r
+\r
+ @param[in] PreviousStatus The previous UEFI Variable lock attempt status.\r
+ @param[in] VariableLock The EDK II Variable Lock Protocol instance.\r
+ @param[in] VariableName The name of the UEFI Variable to lock.\r
+\r
+ @retval EFI_SUCCESS The UEFI Variable was locked and the previous variable\r
+ lock attempt also succeeded.\r
+ @retval Other The UEFI Variable could not be locked or the previous\r
+ variable lock attempt failed.\r
+**/\r
+static\r
+EFI_STATUS\r
+LockFmpVariable (\r
+ IN EFI_STATUS PreviousStatus,\r
+ IN EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock,\r
+ IN CHAR16 *VariableName\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = VariableLock->RequestToLock (\r
+ VariableLock,\r
+ VariableName,\r
+ &gEfiCallerIdGuid\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ return PreviousStatus;\r
+ }\r
+\r
+ DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variable %g %s. Status = %r\n",\r
+ &gEfiCallerIdGuid,\r
+ VariableName,\r
+ Status\r
+ ));\r
+\r
+ if (EFI_ERROR (PreviousStatus)) {\r
+ return PreviousStatus;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently\r
+ executing module.\r
+\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
@retval EFI_SUCCESS All UEFI variables are locked.\r
@retval EFI_UNSUPPORTED Variable Lock Protocol not found.\r
@retval Other One of the UEFI variables could not be locked.\r
-\r
**/\r
EFI_STATUS\r
LockAllFmpVariables (\r
- VOID\r
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
)\r
{\r
EFI_STATUS Status;\r
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
- EFI_STATUS ReturnStatus;\r
- UINTN Index;\r
\r
VariableLock = NULL;\r
Status = gBS->LocateProtocol (\r
NULL,\r
(VOID **)&VariableLock\r
);\r
- if (EFI_ERROR (Status)) {\r
+ if (EFI_ERROR (Status) || VariableLock == NULL) {\r
DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to locate Variable Lock Protocol (%r).\n", Status));\r
return EFI_UNSUPPORTED;\r
}\r
\r
- ReturnStatus = EFI_SUCCESS;\r
- for (Index = 0; Index < ARRAY_SIZE (mFmpVariableLockList); Index++) {\r
- Status = VariableLock->RequestToLock (\r
- VariableLock,\r
- (CHAR16 *)mFmpVariableLockList[Index],\r
- &gEfiCallerIdGuid\r
- );\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variable %g %s. Status = %r\n",\r
- &gEfiCallerIdGuid,\r
- mFmpVariableLockList[Index],\r
- Status\r
- ));\r
- if (!EFI_ERROR (ReturnStatus)) {\r
- ReturnStatus = Status;\r
- }\r
- }\r
- }\r
+ Status = EFI_SUCCESS;\r
+ Status = LockFmpVariable (Status, VariableLock, Private->VersionVariableName);\r
+ Status = LockFmpVariable (Status, VariableLock, Private->LsvVariableName);\r
+ Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptStatusVariableName);\r
+ Status = LockFmpVariable (Status, VariableLock, Private->LastAttemptVersionVariableName);\r
+ Status = LockFmpVariable (Status, VariableLock, Private->FmpStateVariableName);\r
\r
- return ReturnStatus;\r
+ return Status;\r
}\r
firmware updates.\r
\r
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>\r
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>\r
\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
#ifndef __VARIABLE_SUPPORT_H__\r
#define __VARIABLE_SUPPORT_H__\r
\r
+///\r
+/// Default values for FMP Controller State information\r
+///\r
#define DEFAULT_VERSION 0x1\r
#define DEFAULT_LOWESTSUPPORTEDVERSION 0x0\r
-#define DEFAULT_LASTATTEMPT 0x0\r
+#define DEFAULT_LASTATTEMPTSTATUS 0x0\r
+#define DEFAULT_LASTATTEMPTVERSION 0x0\r
\r
+///\r
+/// Base UEFI Variable names for FMP Controller State information stored in\r
+/// separate variables.\r
+///\r
#define VARNAME_VERSION L"FmpVersion"\r
#define VARNAME_LSV L"FmpLsv"\r
-\r
#define VARNAME_LASTATTEMPTSTATUS L"LastAttemptStatus"\r
#define VARNAME_LASTATTEMPTVERSION L"LastAttemptVersion"\r
\r
+///\r
+/// Base UEFI Variable name for FMP Controller State information stored in a\r
+/// merged UEFI Variable. If the separate UEFI Variables above are detected,\r
+/// then they are merged into a single variable and the separate variables are\r
+/// deleted.\r
+///\r
+#define VARNAME_FMPSTATE L"FmpState"\r
+\r
+///\r
+/// FMP Controller State structure that is used to store the state of\r
+/// a controller in one combined UEFI Variable.\r
+///\r
+typedef struct {\r
+ BOOLEAN VersionValid;\r
+ BOOLEAN LsvValid;\r
+ BOOLEAN LastAttemptStatusValid;\r
+ BOOLEAN LastAttemptVersionValid;\r
+ UINT32 Version;\r
+ UINT32 Lsv;\r
+ UINT32 LastAttemptStatus;\r
+ UINT32 LastAttemptVersion;\r
+} FMP_CONTROLLER_STATE;\r
+\r
+/**\r
+ Generate the names of the UEFI Variables used to store state information for\r
+ a managed controller. The UEFI Variables names are a combination of a base\r
+ name and an optional hardware instance value as a 16 character hex value. If\r
+ the hardware instance value is 0, then the 16 character hex value is not\r
+ included. These storage for the UEFI Variable names are allocated using the\r
+ UEFI Boot Service AllocatePool() and the pointers are stored in the Private.\r
+ The following are examples of variable names produces for hardware instance\r
+ value 0 and value 0x1234567812345678.\r
+\r
+ FmpVersion\r
+ FmpLsv\r
+ LastAttemptStatus\r
+ LastAttemptVersion\r
+ FmpDxe\r
+\r
+ FmpVersion1234567812345678\r
+ FmpLsv1234567812345678\r
+ LastAttemptStatus1234567812345678\r
+ LastAttemptVersion1234567812345678\r
+ FmpDxe1234567812345678\r
+\r
+ @param[in,out] Private Private context structure for the managed controller.\r
+**/\r
+VOID\r
+GenerateFmpVariableNames (\r
+ IN OUT FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
+ );\r
+\r
/**\r
Returns the value used to fill in the Version field of the\r
EFI_FIRMWARE_IMAGE_DESCRIPTOR structure that is returned by the GetImageInfo()\r
variable. If the UEFI variables does not exist, then a default version value\r
is returned.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
\r
- @return The version of the firmware image in the firmware device.\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
+ @return The version of the firmware image in the firmware device.\r
**/\r
UINT32\r
GetVersionFromVariable (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
);\r
\r
/**\r
variable. If the UEFI variables does not exist, then a default lowest\r
supported version value is returned.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
+\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
@return The lowest supported version of the firmware image in the firmware\r
device.\r
-\r
**/\r
UINT32\r
GetLowestSupportedVersionFromVariable (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
);\r
\r
/**\r
variable. If the UEFI variables does not exist, then a default last attempt\r
status value is returned.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
\r
- @return The last attempt status value for the most recent capsule update.\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
+ @return The last attempt status value for the most recent capsule update.\r
**/\r
UINT32\r
GetLastAttemptStatusFromVariable (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
);\r
\r
/**\r
variable. If the UEFI variables does not exist, then a default last attempt\r
version value is returned.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
\r
- @return The last attempt version value for the most recent capsule update.\r
+ @param[in] Private Private context structure for the managed controller.\r
\r
+ @return The last attempt version value for the most recent capsule update.\r
**/\r
UINT32\r
GetLastAttemptVersionFromVariable (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
);\r
\r
/**\r
Saves the version current of the firmware image in the firmware device to a\r
UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpVersion"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
\r
+ @param[in] Private Private context structure for the managed controller.\r
@param[in] Version The version of the firmware image in the firmware device.\r
-\r
**/\r
VOID\r
SetVersionInVariable (\r
- UINT32 Version\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 Version\r
);\r
\r
/**\r
Saves the lowest supported version current of the firmware image in the\r
firmware device to a UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpLsv"\r
-\r
- @param[in] LowestSupportedVersion The lowest supported version of the firmware image\r
- in the firmware device.\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
\r
+ @param[in] Private Private context structure for the managed\r
+ controller.\r
+ @param[in] LowestSupportedVersion The lowest supported version of the\r
+ firmware image in the firmware device.\r
**/\r
VOID\r
SetLowestSupportedVersionInVariable (\r
- UINT32 LowestSupportedVersion\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 LowestSupportedVersion\r
);\r
\r
/**\r
Saves the last attempt status value of the most recent FMP capsule update to a\r
UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptStatus"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
\r
+ @param[in] Private Private context structure for the managed\r
+ controller.\r
@param[in] LastAttemptStatus The last attempt status of the most recent FMP\r
capsule update.\r
-\r
**/\r
VOID\r
SetLastAttemptStatusInVariable (\r
- UINT32 LastAttemptStatus\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 LastAttemptStatus\r
);\r
\r
/**\r
Saves the last attempt version value of the most recent FMP capsule update to\r
a UEFI variable.\r
\r
- UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"LastAttemptVersion"\r
+ UEFI Variable accessed: GUID = gEfiCallerIdGuid, Name = L"FmpDxe"\r
\r
+ @param[in] Private Private context structure for the managed\r
+ controller.\r
@param[in] LastAttemptVersion The last attempt version value of the most\r
recent FMP capsule update.\r
-\r
**/\r
VOID\r
SetLastAttemptVersionInVariable (\r
- UINT32 LastAttemptVersion\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private,\r
+ IN UINT32 LastAttemptVersion\r
);\r
\r
/**\r
Locks all the UEFI Variables that use gEfiCallerIdGuid of the currently\r
executing module.\r
\r
+ @param[in] Private Private context structure for the managed controller.\r
+\r
+ @retval EFI_SUCCESS All UEFI variables are locked.\r
+ @retval EFI_UNSUPPORTED Variable Lock Protocol not found.\r
+ @retval Other One of the UEFI variables could not be locked.\r
**/\r
EFI_STATUS\r
LockAllFmpVariables (\r
- VOID\r
+ IN FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private\r
);\r
\r
#endif\r