/** @file\r
DXE capsule report related function.\r
\r
- Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include <PiDxe.h>\r
#include <Protocol/FirmwareManagement.h>\r
-#include <Protocol/VariableLock.h>\r
#include <Guid/CapsuleReport.h>\r
#include <Guid/FmpCapsule.h>\r
#include <Guid/CapsuleVendor.h>\r
#include <Library/ReportStatusCodeLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/CapsuleLib.h>\r
+#include <Library/VariablePolicyHelperLib.h>\r
\r
#include <IndustryStandard/WindowsUxCapsule.h>\r
\r
-typedef struct {\r
- EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultHeader;\r
- EFI_CAPSULE_RESULT_VARIABLE_FMP CapsuleResultFmp;\r
-} CAPSULE_RESULT_VARIABLE_CACHE;\r
+/**\r
+ This routine is called to clear CapsuleOnDisk Relocation Info variable.\r
+ Total Capsule On Disk length is recorded in this variable\r
\r
-#define CAPSULE_RESULT_VARIABLE_CACHE_COUNT 0x10\r
+ @retval EFI_SUCCESS Capsule On Disk flags are cleared\r
\r
-CAPSULE_RESULT_VARIABLE_CACHE *mCapsuleResultVariableCache;\r
-UINTN mCapsuleResultVariableCacheMaxCount;\r
-UINTN mCapsuleResultVariableCacheCount;\r
+**/\r
+EFI_STATUS\r
+CoDClearCapsuleRelocationInfo(\r
+ VOID\r
+ );\r
\r
/**\r
Get current capsule last variable index.\r
return CurrentIndex;\r
}\r
\r
-/**\r
- Check if this FMP capsule is processed.\r
-\r
- @param[in] CapsuleHeader The capsule image header\r
- @param[in] PayloadIndex FMP payload index\r
- @param[in] ImageHeader FMP image header\r
-\r
- @retval TRUE This FMP capsule is processed.\r
- @retval FALSE This FMP capsule is not processed.\r
-**/\r
-BOOLEAN\r
-IsFmpCapsuleProcessed (\r
- IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
- IN UINTN PayloadIndex,\r
- IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader\r
- )\r
-{\r
- UINTN Index;\r
- EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult;\r
- EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp;\r
-\r
- for (Index = 0; Index < mCapsuleResultVariableCacheCount; Index++) {\r
- //\r
- // Check\r
- //\r
- CapsuleResult = &mCapsuleResultVariableCache[Index].CapsuleResultHeader;\r
- if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {\r
- if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {\r
- if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) * 2) {\r
- CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);\r
- if (CompareGuid(&CapsuleResultFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId) &&\r
- (CapsuleResultFmp->UpdateImageIndex == ImageHeader->UpdateImageIndex) &&\r
- (CapsuleResultFmp->PayloadIndex == PayloadIndex) ) {\r
- return TRUE;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-/**\r
- Write a new capsule status variable cache.\r
-\r
- @param[in] CapsuleResult The capsule status variable\r
- @param[in] CapsuleResultSize The size of the capsule stauts variable in bytes\r
-\r
- @retval EFI_SUCCESS The capsule status variable is cached.\r
- @retval EFI_OUT_OF_RESOURCES No resource to cache the capsule status variable.\r
-**/\r
-EFI_STATUS\r
-WriteNewCapsuleResultVariableCache (\r
- IN VOID *CapsuleResult,\r
- IN UINTN CapsuleResultSize\r
- )\r
-{\r
- if (CapsuleResultSize > sizeof(CAPSULE_RESULT_VARIABLE_CACHE)) {\r
- CapsuleResultSize = sizeof(CAPSULE_RESULT_VARIABLE_CACHE);\r
- }\r
-\r
- if (mCapsuleResultVariableCacheCount == mCapsuleResultVariableCacheMaxCount) {\r
- mCapsuleResultVariableCache = ReallocatePool(\r
- mCapsuleResultVariableCacheMaxCount * sizeof(CAPSULE_RESULT_VARIABLE_CACHE),\r
- (mCapsuleResultVariableCacheMaxCount + CAPSULE_RESULT_VARIABLE_CACHE_COUNT) * sizeof(CAPSULE_RESULT_VARIABLE_CACHE),\r
- mCapsuleResultVariableCache\r
- );\r
- if (mCapsuleResultVariableCache == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- mCapsuleResultVariableCacheMaxCount += CAPSULE_RESULT_VARIABLE_CACHE_COUNT;\r
- }\r
-\r
- ASSERT(mCapsuleResultVariableCacheCount < mCapsuleResultVariableCacheMaxCount);\r
- ASSERT(mCapsuleResultVariableCache != NULL);\r
- CopyMem(\r
- &mCapsuleResultVariableCache[mCapsuleResultVariableCacheCount],\r
- CapsuleResult,\r
- CapsuleResultSize\r
- );\r
- mCapsuleResultVariableCacheCount++;\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
/**\r
Get a new capsule status variable index.\r
\r
return CurrentIndex + 1;\r
}\r
\r
+/**\r
+ Lock Variable by variable policy.\r
+\r
+ @param[in] VariableGuid The Guid of the variable to be locked\r
+ @param[in] VariableName The name of the variable to be locked\r
+ @param[in] VariablePolicy The pointer of variable lock policy\r
+**/\r
+VOID\r
+LockVariable (\r
+ IN CONST EFI_GUID VariableGuid,\r
+ IN CHAR16 *VariableName,\r
+ IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ // Set the policies to protect the target variables\r
+ Status = RegisterBasicVariablePolicy (VariablePolicy,\r
+ &VariableGuid,\r
+ VariableName,\r
+ VARIABLE_POLICY_NO_MIN_SIZE,\r
+ VARIABLE_POLICY_NO_MAX_SIZE,\r
+ VARIABLE_POLICY_NO_MUST_ATTR,\r
+ VARIABLE_POLICY_NO_CANT_ATTR,\r
+ VARIABLE_POLICY_TYPE_LOCK_NOW);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "DxeCapsuleLibFmp: Failed to lock variable %g %s. Status = %r\n",\r
+ &VariableGuid,\r
+ VariableName,\r
+ Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
+}\r
+\r
/**\r
Write a new capsule status variable.\r
\r
gRT->GetTime(&CapsuleResultVariable.CapsuleProcessed, NULL);\r
CapsuleResultVariable.CapsuleStatus = CapsuleStatus;\r
\r
- //\r
- // Save Local Cache\r
- //\r
- Status = WriteNewCapsuleResultVariableCache(&CapsuleResultVariable, sizeof(CapsuleResultVariable));\r
-\r
+ Status = EFI_SUCCESS;\r
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
Status = WriteNewCapsuleResultVariable(&CapsuleResultVariable, sizeof(CapsuleResultVariable));\r
}\r
@param[in] PayloadIndex FMP payload index\r
@param[in] ImageHeader FMP image header\r
@param[in] FmpDevicePath DevicePath associated with the FMP producer\r
+ @param[in] CapFileName Capsule file name\r
\r
@retval EFI_SUCCESS The capsule status variable is recorded.\r
@retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\r
IN EFI_STATUS CapsuleStatus,\r
IN UINTN PayloadIndex,\r
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
- IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL,\r
+ IN CHAR16 *CapFileName OPTIONAL\r
)\r
{\r
EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader;\r
UINTN CapsuleResultVariableSize;\r
CHAR16 *DevicePathStr;\r
UINTN DevicePathStrSize;\r
+ UINTN CapFileNameSize;\r
+\r
+ DevicePathStr = NULL;\r
+ CapFileNameSize = sizeof(CHAR16);\r
\r
- DevicePathStr = NULL;\r
if (FmpDevicePath != NULL) {\r
DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE);\r
}\r
} else {\r
DevicePathStrSize = sizeof(CHAR16);\r
}\r
+\r
+ if (CapFileName != NULL) {\r
+ CapFileNameSize = StrSize(CapFileName);\r
+ }\r
+\r
//\r
- // Allocate zero CHAR16 for CapsuleFileName.\r
+ // Allocate room for CapsuleFileName.\r
//\r
- CapsuleResultVariableSize = sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) + DevicePathStrSize;\r
+ CapsuleResultVariableSize = sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize + DevicePathStrSize;\r
+\r
CapsuleResultVariable = AllocateZeroPool (CapsuleResultVariableSize);\r
if (CapsuleResultVariable == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;\r
CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader->UpdateImageIndex;\r
CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId);\r
+\r
+ if (CapFileName != NULL) {\r
+ CopyMem((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName, CapFileNameSize);\r
+ }\r
+\r
if (DevicePathStr != NULL) {\r
- CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16), DevicePathStr, DevicePathStrSize);\r
+ CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize, DevicePathStr, DevicePathStrSize);\r
FreePool (DevicePathStr);\r
DevicePathStr = NULL;\r
}\r
\r
- //\r
- // Save Local Cache\r
- //\r
- Status = WriteNewCapsuleResultVariableCache(CapsuleResultVariable, CapsuleResultVariableSize);\r
-\r
+ Status = EFI_SUCCESS;\r
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {\r
Status = WriteNewCapsuleResultVariable(CapsuleResultVariable, CapsuleResultVariableSize);\r
}\r
\r
/**\r
Initialize CapsuleMax variables.\r
+\r
+ @param[in] VariablePolicy The pointer of variable lock policy\r
**/\r
VOID\r
InitCapsuleMaxVariable (\r
- VOID\r
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy\r
)\r
{\r
EFI_STATUS Status;\r
UINTN Size;\r
CHAR16 CapsuleMaxStr[sizeof("Capsule####")];\r
- EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
\r
UnicodeSPrint(\r
CapsuleMaxStr,\r
);\r
if (!EFI_ERROR(Status)) {\r
// Lock it per UEFI spec.\r
- Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);\r
- if (!EFI_ERROR(Status)) {\r
- Status = VariableLock->RequestToLock(VariableLock, L"CapsuleMax", &gEfiCapsuleReportGuid);\r
- ASSERT_EFI_ERROR(Status);\r
- }\r
+ LockVariable (gEfiCapsuleReportGuid, L"CapsuleMax", VariablePolicy);\r
}\r
}\r
\r
/**\r
Initialize CapsuleLast variables.\r
+\r
+ @param[in] VariablePolicy The pointer of variable lock policy\r
**/\r
VOID\r
InitCapsuleLastVariable (\r
- VOID\r
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy\r
)\r
{\r
EFI_STATUS Status;\r
EFI_BOOT_MODE BootMode;\r
- EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;\r
VOID *CapsuleResult;\r
UINTN Size;\r
CHAR16 CapsuleLastStr[sizeof("Capsule####")];\r
0,\r
NULL\r
);\r
+ } else {\r
+ if (CapsuleResult != NULL) {\r
+ FreePool (CapsuleResult);\r
+ }\r
}\r
}\r
\r
// Lock it in normal boot path per UEFI spec.\r
- Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);\r
- if (!EFI_ERROR(Status)) {\r
- Status = VariableLock->RequestToLock(VariableLock, L"CapsuleLast", &gEfiCapsuleReportGuid);\r
- ASSERT_EFI_ERROR(Status);\r
- }\r
+ LockVariable (gEfiCapsuleReportGuid, L"CapsuleLast", VariablePolicy);\r
}\r
}\r
\r
Index = 0;\r
while (TRUE) {\r
if (Index > 0) {\r
- UnicodeValueToString (TempVarName, 0, Index, 0);\r
+ UnicodeValueToStringS (\r
+ TempVarName,\r
+ sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),\r
+ 0,\r
+ Index,\r
+ 0\r
+ );\r
}\r
Status = gRT->SetVariable (\r
CapsuleVarName,\r
}\r
}\r
\r
+/**\r
+ Initialize capsule relocation info variable.\r
+\r
+ @param[in] VariablePolicy The pointer of variable lock policy\r
+**/\r
+VOID\r
+InitCapsuleRelocationInfo (\r
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy\r
+ )\r
+{\r
+ CoDClearCapsuleRelocationInfo();\r
+\r
+ //\r
+ // Unlock Capsule On Disk relocation Info variable only when Capsule On Disk flag is enabled\r
+ //\r
+ if (!CoDCheckCapsuleOnDiskFlag()) {\r
+ LockVariable (gEfiCapsuleVendorGuid, COD_RELOCATION_INFO_VAR_NAME, VariablePolicy);\r
+ }\r
+}\r
+\r
/**\r
Initialize capsule related variables.\r
**/\r
VOID\r
)\r
{\r
+ EFI_STATUS Status;\r
+ EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;\r
+\r
+ // Locate the VariablePolicy protocol\r
+ Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID**)&VariablePolicy);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "DxeCapsuleReportLib %a - Could not locate VariablePolicy protocol! %r\n", __FUNCTION__, Status));\r
+ ASSERT_EFI_ERROR (Status);\r
+ }\r
InitCapsuleUpdateVariable();\r
- InitCapsuleMaxVariable();\r
- InitCapsuleLastVariable();\r
+ InitCapsuleMaxVariable (VariablePolicy);\r
+ InitCapsuleLastVariable (VariablePolicy);\r
+ InitCapsuleRelocationInfo (VariablePolicy);\r
+\r
//\r
// No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"\r
// to check status and delete them.\r