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