diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c')
| -rw-r--r-- | MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c | 1036 |
1 files changed, 518 insertions, 518 deletions
diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c index a1523428cd..74b6726cef 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleReportLib.c @@ -1,518 +1,518 @@ -/** @file
- DXE capsule report related function.
-
- Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiDxe.h>
-#include <Protocol/FirmwareManagement.h>
-#include <Guid/CapsuleReport.h>
-#include <Guid/FmpCapsule.h>
-#include <Guid/CapsuleVendor.h>
-
-#include <Library/BaseLib.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/UefiRuntimeServicesTableLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiLib.h>
-#include <Library/PcdLib.h>
-#include <Library/HobLib.h>
-#include <Library/PrintLib.h>
-#include <Library/ReportStatusCodeLib.h>
-#include <Library/DevicePathLib.h>
-#include <Library/CapsuleLib.h>
-#include <Library/VariablePolicyHelperLib.h>
-
-#include <IndustryStandard/WindowsUxCapsule.h>
-
-/**
- This routine is called to clear CapsuleOnDisk Relocation Info variable.
- Total Capsule On Disk length is recorded in this variable
-
- @retval EFI_SUCCESS Capsule On Disk flags are cleared
-
-**/
-EFI_STATUS
-CoDClearCapsuleRelocationInfo (
- VOID
- );
-
-/**
- Get current capsule last variable index.
-
- @return Current capsule last variable index.
- @retval -1 No current capsule last variable.
-**/
-INTN
-GetCurrentCapsuleLastIndex (
- VOID
- )
-{
- UINTN Size;
- CHAR16 CapsuleLastStr[sizeof ("Capsule####")];
- EFI_STATUS Status;
- UINT16 CurrentIndex;
-
- Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
- Status = gRT->GetVariable (
- L"CapsuleLast",
- &gEfiCapsuleReportGuid,
- NULL,
- &Size,
- CapsuleLastStr
- );
- if (EFI_ERROR (Status)) {
- return -1;
- }
-
- CurrentIndex = (UINT16)StrHexToUintn (&CapsuleLastStr[sizeof ("Capsule") - 1]);
- return CurrentIndex;
-}
-
-/**
- Get a new capsule status variable index.
-
- @return A new capsule status variable index.
- @retval 0 No new capsule status variable index. Rolling over.
-**/
-INTN
-GetNewCapsuleResultIndex (
- VOID
- )
-{
- INTN CurrentIndex;
-
- CurrentIndex = GetCurrentCapsuleLastIndex ();
- if (CurrentIndex >= PcdGet16 (PcdCapsuleMax)) {
- DEBUG ((DEBUG_INFO, " CapsuleResult variable Rolling Over!\n"));
- return 0;
- }
-
- return CurrentIndex + 1;
-}
-
-/**
- Lock Variable by variable policy.
-
- @param[in] VariableGuid The Guid of the variable to be locked
- @param[in] VariableName The name of the variable to be locked
- @param[in] VariablePolicy The pointer of variable lock policy
-**/
-VOID
-LockVariable (
- IN CONST EFI_GUID VariableGuid,
- IN CHAR16 *VariableName,
- IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
- )
-{
- EFI_STATUS Status;
-
- // Set the policies to protect the target variables
- Status = RegisterBasicVariablePolicy (
- VariablePolicy,
- &VariableGuid,
- VariableName,
- VARIABLE_POLICY_NO_MIN_SIZE,
- VARIABLE_POLICY_NO_MAX_SIZE,
- VARIABLE_POLICY_NO_MUST_ATTR,
- VARIABLE_POLICY_NO_CANT_ATTR,
- VARIABLE_POLICY_TYPE_LOCK_NOW
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((
- DEBUG_ERROR,
- "DxeCapsuleLibFmp: Failed to lock variable %g %s. Status = %r\n",
- &VariableGuid,
- VariableName,
- Status
- ));
- ASSERT_EFI_ERROR (Status);
- }
-}
-
-/**
- Write a new capsule status variable.
-
- @param[in] CapsuleResult The capsule status variable
- @param[in] CapsuleResultSize The size of the capsule stauts variable in bytes
-
- @retval EFI_SUCCESS The capsule status variable is recorded.
- @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
-**/
-EFI_STATUS
-WriteNewCapsuleResultVariable (
- IN VOID *CapsuleResult,
- IN UINTN CapsuleResultSize
- )
-{
- INTN CapsuleResultIndex;
- CHAR16 CapsuleResultStr[sizeof ("Capsule####")];
- UINTN Size;
- EFI_STATUS Status;
-
- CapsuleResultIndex = GetNewCapsuleResultIndex ();
- DEBUG ((DEBUG_INFO, "New CapsuleResultIndex - 0x%x\n", CapsuleResultIndex));
-
- UnicodeSPrint (
- CapsuleResultStr,
- sizeof (CapsuleResultStr),
- L"Capsule%04x",
- CapsuleResultIndex
- );
-
- Status = gRT->SetVariable (
- CapsuleResultStr,
- &gEfiCapsuleReportGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- CapsuleResultSize,
- CapsuleResult
- );
- if (!EFI_ERROR (Status)) {
- Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
- DEBUG ((DEBUG_INFO, "Set CapsuleLast - %s\n", CapsuleResultStr));
- Status = gRT->SetVariable (
- L"CapsuleLast",
- &gEfiCapsuleReportGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- Size,
- CapsuleResultStr
- );
- }
-
- return Status;
-}
-
-/**
- Record capsule status variable and to local cache.
-
- @param[in] CapsuleHeader The capsule image header
- @param[in] CapsuleStatus The capsule process stauts
-
- @retval EFI_SUCCESS The capsule status variable is recorded.
- @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
-**/
-EFI_STATUS
-RecordCapsuleStatusVariable (
- IN EFI_CAPSULE_HEADER *CapsuleHeader,
- IN EFI_STATUS CapsuleStatus
- )
-{
- EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultVariable;
- EFI_STATUS Status;
-
- CapsuleResultVariable.VariableTotalSize = sizeof (CapsuleResultVariable);
- CapsuleResultVariable.Reserved = 0;
- CopyGuid (&CapsuleResultVariable.CapsuleGuid, &CapsuleHeader->CapsuleGuid);
- ZeroMem (&CapsuleResultVariable.CapsuleProcessed, sizeof (CapsuleResultVariable.CapsuleProcessed));
- gRT->GetTime (&CapsuleResultVariable.CapsuleProcessed, NULL);
- CapsuleResultVariable.CapsuleStatus = CapsuleStatus;
-
- Status = EFI_SUCCESS;
- if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
- Status = WriteNewCapsuleResultVariable (&CapsuleResultVariable, sizeof (CapsuleResultVariable));
- }
-
- return Status;
-}
-
-/**
- Record FMP capsule status variable and to local cache.
-
- @param[in] CapsuleHeader The capsule image header
- @param[in] CapsuleStatus The capsule process stauts
- @param[in] PayloadIndex FMP payload index
- @param[in] ImageHeader FMP image header
- @param[in] FmpDevicePath DevicePath associated with the FMP producer
- @param[in] CapFileName Capsule file name
-
- @retval EFI_SUCCESS The capsule status variable is recorded.
- @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.
-**/
-EFI_STATUS
-RecordFmpCapsuleStatusVariable (
- IN EFI_CAPSULE_HEADER *CapsuleHeader,
- IN EFI_STATUS CapsuleStatus,
- IN UINTN PayloadIndex,
- IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
- IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL,
- IN CHAR16 *CapFileName OPTIONAL
- )
-{
- EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader;
- EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp;
- EFI_STATUS Status;
- UINT8 *CapsuleResultVariable;
- UINTN CapsuleResultVariableSize;
- CHAR16 *DevicePathStr;
- UINTN DevicePathStrSize;
- UINTN CapFileNameSize;
-
- DevicePathStr = NULL;
- CapFileNameSize = sizeof (CHAR16);
-
- if (FmpDevicePath != NULL) {
- DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE);
- }
-
- if (DevicePathStr != NULL) {
- DevicePathStrSize = StrSize (DevicePathStr);
- } else {
- DevicePathStrSize = sizeof (CHAR16);
- }
-
- if (CapFileName != NULL) {
- CapFileNameSize = StrSize (CapFileName);
- }
-
- //
- // Allocate room for CapsuleFileName.
- //
- CapsuleResultVariableSize = sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize + DevicePathStrSize;
-
- CapsuleResultVariable = AllocateZeroPool (CapsuleResultVariableSize);
- if (CapsuleResultVariable == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
-
- CapsuleResultVariableHeader = (VOID *)CapsuleResultVariable;
- CapsuleResultVariableHeader->VariableTotalSize = (UINT32)CapsuleResultVariableSize;
- CapsuleResultVariableHeader->Reserved = 0;
- CopyGuid (&CapsuleResultVariableHeader->CapsuleGuid, &CapsuleHeader->CapsuleGuid);
- ZeroMem (&CapsuleResultVariableHeader->CapsuleProcessed, sizeof (CapsuleResultVariableHeader->CapsuleProcessed));
- gRT->GetTime (&CapsuleResultVariableHeader->CapsuleProcessed, NULL);
- CapsuleResultVariableHeader->CapsuleStatus = CapsuleStatus;
-
- CapsuleResultVariableFmp = (VOID *)(CapsuleResultVariable + sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER));
- CapsuleResultVariableFmp->Version = 0x1;
- CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex;
- CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader->UpdateImageIndex;
- CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId);
-
- if (CapFileName != NULL) {
- CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName, CapFileNameSize);
- }
-
- if (DevicePathStr != NULL) {
- CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize, DevicePathStr, DevicePathStrSize);
- FreePool (DevicePathStr);
- DevicePathStr = NULL;
- }
-
- Status = EFI_SUCCESS;
- if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
- Status = WriteNewCapsuleResultVariable (CapsuleResultVariable, CapsuleResultVariableSize);
- }
-
- FreePool (CapsuleResultVariable);
- return Status;
-}
-
-/**
- Initialize CapsuleMax variables.
-
- @param[in] VariablePolicy The pointer of variable lock policy
-**/
-VOID
-InitCapsuleMaxVariable (
- EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
- )
-{
- EFI_STATUS Status;
- UINTN Size;
- CHAR16 CapsuleMaxStr[sizeof ("Capsule####")];
-
- UnicodeSPrint (
- CapsuleMaxStr,
- sizeof (CapsuleMaxStr),
- L"Capsule%04x",
- PcdGet16 (PcdCapsuleMax)
- );
-
- Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
- Status = gRT->SetVariable (
- L"CapsuleMax",
- &gEfiCapsuleReportGuid,
- EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- Size,
- CapsuleMaxStr
- );
- if (!EFI_ERROR (Status)) {
- // Lock it per UEFI spec.
- LockVariable (gEfiCapsuleReportGuid, L"CapsuleMax", VariablePolicy);
- }
-}
-
-/**
- Initialize CapsuleLast variables.
-
- @param[in] VariablePolicy The pointer of variable lock policy
-**/
-VOID
-InitCapsuleLastVariable (
- EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
- )
-{
- EFI_STATUS Status;
- EFI_BOOT_MODE BootMode;
- VOID *CapsuleResult;
- UINTN Size;
- CHAR16 CapsuleLastStr[sizeof ("Capsule####")];
-
- BootMode = GetBootModeHob ();
- if (BootMode == BOOT_ON_FLASH_UPDATE) {
- Status = gRT->SetVariable (
- L"CapsuleLast",
- &gEfiCapsuleReportGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- 0,
- NULL
- );
- // Do not lock it because it will be updated later.
- } else {
- //
- // Check if OS/APP cleared L"Capsule####"
- //
- ZeroMem (CapsuleLastStr, sizeof (CapsuleLastStr));
- Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator
- Status = gRT->GetVariable (
- L"CapsuleLast",
- &gEfiCapsuleReportGuid,
- NULL,
- &Size,
- CapsuleLastStr
- );
- if (!EFI_ERROR (Status)) {
- //
- // L"CapsuleLast" is got, check if data is there.
- //
- Status = GetVariable2 (
- CapsuleLastStr,
- &gEfiCapsuleReportGuid,
- (VOID **)&CapsuleResult,
- NULL
- );
- if (EFI_ERROR (Status)) {
- //
- // If no data, delete L"CapsuleLast"
- //
- Status = gRT->SetVariable (
- L"CapsuleLast",
- &gEfiCapsuleReportGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
- 0,
- NULL
- );
- } else {
- if (CapsuleResult != NULL) {
- FreePool (CapsuleResult);
- }
- }
- }
-
- // Lock it in normal boot path per UEFI spec.
- LockVariable (gEfiCapsuleReportGuid, L"CapsuleLast", VariablePolicy);
- }
-}
-
-/**
- Initialize capsule update variables.
-**/
-VOID
-InitCapsuleUpdateVariable (
- VOID
- )
-{
- EFI_STATUS Status;
- UINTN Index;
- CHAR16 CapsuleVarName[30];
- CHAR16 *TempVarName;
-
- //
- // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2...
- // as early as possible which will avoid the next time boot after the capsule update
- // will still into the capsule loop
- //
- StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), EFI_CAPSULE_VARIABLE_NAME);
- TempVarName = CapsuleVarName + StrLen (CapsuleVarName);
- Index = 0;
- while (TRUE) {
- if (Index > 0) {
- UnicodeValueToStringS (
- TempVarName,
- sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName),
- 0,
- Index,
- 0
- );
- }
-
- Status = gRT->SetVariable (
- CapsuleVarName,
- &gEfiCapsuleVendorGuid,
- EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
- 0,
- (VOID *)NULL
- );
- if (EFI_ERROR (Status)) {
- //
- // There is no capsule variables, quit
- //
- break;
- }
-
- Index++;
- }
-}
-
-/**
- Initialize capsule relocation info variable.
-
- @param[in] VariablePolicy The pointer of variable lock policy
-**/
-VOID
-InitCapsuleRelocationInfo (
- EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy
- )
-{
- CoDClearCapsuleRelocationInfo ();
-
- //
- // Unlock Capsule On Disk relocation Info variable only when Capsule On Disk flag is enabled
- //
- if (!CoDCheckCapsuleOnDiskFlag ()) {
- LockVariable (gEfiCapsuleVendorGuid, COD_RELOCATION_INFO_VAR_NAME, VariablePolicy);
- }
-}
-
-/**
- Initialize capsule related variables.
-**/
-VOID
-InitCapsuleVariable (
- VOID
- )
-{
- EFI_STATUS Status;
- EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy;
-
- // Locate the VariablePolicy protocol
- Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy);
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "DxeCapsuleReportLib %a - Could not locate VariablePolicy protocol! %r\n", __func__, Status));
- ASSERT_EFI_ERROR (Status);
- }
-
- InitCapsuleUpdateVariable ();
- InitCapsuleMaxVariable (VariablePolicy);
- InitCapsuleLastVariable (VariablePolicy);
- InitCapsuleRelocationInfo (VariablePolicy);
-
- //
- // No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"
- // to check status and delete them.
- //
-}
+/** @file + DXE capsule report related function. + + Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> +#include <Protocol/FirmwareManagement.h> +#include <Guid/CapsuleReport.h> +#include <Guid/FmpCapsule.h> +#include <Guid/CapsuleVendor.h> + +#include <Library/BaseLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/UefiRuntimeServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/UefiLib.h> +#include <Library/PcdLib.h> +#include <Library/HobLib.h> +#include <Library/PrintLib.h> +#include <Library/ReportStatusCodeLib.h> +#include <Library/DevicePathLib.h> +#include <Library/CapsuleLib.h> +#include <Library/VariablePolicyHelperLib.h> + +#include <IndustryStandard/WindowsUxCapsule.h> + +/** + This routine is called to clear CapsuleOnDisk Relocation Info variable. + Total Capsule On Disk length is recorded in this variable + + @retval EFI_SUCCESS Capsule On Disk flags are cleared + +**/ +EFI_STATUS +CoDClearCapsuleRelocationInfo ( + VOID + ); + +/** + Get current capsule last variable index. + + @return Current capsule last variable index. + @retval -1 No current capsule last variable. +**/ +INTN +GetCurrentCapsuleLastIndex ( + VOID + ) +{ + UINTN Size; + CHAR16 CapsuleLastStr[sizeof ("Capsule####")]; + EFI_STATUS Status; + UINT16 CurrentIndex; + + Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator + Status = gRT->GetVariable ( + L"CapsuleLast", + &gEfiCapsuleReportGuid, + NULL, + &Size, + CapsuleLastStr + ); + if (EFI_ERROR (Status)) { + return -1; + } + + CurrentIndex = (UINT16)StrHexToUintn (&CapsuleLastStr[sizeof ("Capsule") - 1]); + return CurrentIndex; +} + +/** + Get a new capsule status variable index. + + @return A new capsule status variable index. + @retval 0 No new capsule status variable index. Rolling over. +**/ +INTN +GetNewCapsuleResultIndex ( + VOID + ) +{ + INTN CurrentIndex; + + CurrentIndex = GetCurrentCapsuleLastIndex (); + if (CurrentIndex >= PcdGet16 (PcdCapsuleMax)) { + DEBUG ((DEBUG_INFO, " CapsuleResult variable Rolling Over!\n")); + return 0; + } + + return CurrentIndex + 1; +} + +/** + Lock Variable by variable policy. + + @param[in] VariableGuid The Guid of the variable to be locked + @param[in] VariableName The name of the variable to be locked + @param[in] VariablePolicy The pointer of variable lock policy +**/ +VOID +LockVariable ( + IN CONST EFI_GUID VariableGuid, + IN CHAR16 *VariableName, + IN EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy + ) +{ + EFI_STATUS Status; + + // Set the policies to protect the target variables + Status = RegisterBasicVariablePolicy ( + VariablePolicy, + &VariableGuid, + VariableName, + VARIABLE_POLICY_NO_MIN_SIZE, + VARIABLE_POLICY_NO_MAX_SIZE, + VARIABLE_POLICY_NO_MUST_ATTR, + VARIABLE_POLICY_NO_CANT_ATTR, + VARIABLE_POLICY_TYPE_LOCK_NOW + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "DxeCapsuleLibFmp: Failed to lock variable %g %s. Status = %r\n", + &VariableGuid, + VariableName, + Status + )); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Write a new capsule status variable. + + @param[in] CapsuleResult The capsule status variable + @param[in] CapsuleResultSize The size of the capsule stauts variable in bytes + + @retval EFI_SUCCESS The capsule status variable is recorded. + @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable. +**/ +EFI_STATUS +WriteNewCapsuleResultVariable ( + IN VOID *CapsuleResult, + IN UINTN CapsuleResultSize + ) +{ + INTN CapsuleResultIndex; + CHAR16 CapsuleResultStr[sizeof ("Capsule####")]; + UINTN Size; + EFI_STATUS Status; + + CapsuleResultIndex = GetNewCapsuleResultIndex (); + DEBUG ((DEBUG_INFO, "New CapsuleResultIndex - 0x%x\n", CapsuleResultIndex)); + + UnicodeSPrint ( + CapsuleResultStr, + sizeof (CapsuleResultStr), + L"Capsule%04x", + CapsuleResultIndex + ); + + Status = gRT->SetVariable ( + CapsuleResultStr, + &gEfiCapsuleReportGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + CapsuleResultSize, + CapsuleResult + ); + if (!EFI_ERROR (Status)) { + Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator + DEBUG ((DEBUG_INFO, "Set CapsuleLast - %s\n", CapsuleResultStr)); + Status = gRT->SetVariable ( + L"CapsuleLast", + &gEfiCapsuleReportGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + Size, + CapsuleResultStr + ); + } + + return Status; +} + +/** + Record capsule status variable and to local cache. + + @param[in] CapsuleHeader The capsule image header + @param[in] CapsuleStatus The capsule process stauts + + @retval EFI_SUCCESS The capsule status variable is recorded. + @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable. +**/ +EFI_STATUS +RecordCapsuleStatusVariable ( + IN EFI_CAPSULE_HEADER *CapsuleHeader, + IN EFI_STATUS CapsuleStatus + ) +{ + EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultVariable; + EFI_STATUS Status; + + CapsuleResultVariable.VariableTotalSize = sizeof (CapsuleResultVariable); + CapsuleResultVariable.Reserved = 0; + CopyGuid (&CapsuleResultVariable.CapsuleGuid, &CapsuleHeader->CapsuleGuid); + ZeroMem (&CapsuleResultVariable.CapsuleProcessed, sizeof (CapsuleResultVariable.CapsuleProcessed)); + gRT->GetTime (&CapsuleResultVariable.CapsuleProcessed, NULL); + CapsuleResultVariable.CapsuleStatus = CapsuleStatus; + + Status = EFI_SUCCESS; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) { + Status = WriteNewCapsuleResultVariable (&CapsuleResultVariable, sizeof (CapsuleResultVariable)); + } + + return Status; +} + +/** + Record FMP capsule status variable and to local cache. + + @param[in] CapsuleHeader The capsule image header + @param[in] CapsuleStatus The capsule process stauts + @param[in] PayloadIndex FMP payload index + @param[in] ImageHeader FMP image header + @param[in] FmpDevicePath DevicePath associated with the FMP producer + @param[in] CapFileName Capsule file name + + @retval EFI_SUCCESS The capsule status variable is recorded. + @retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable. +**/ +EFI_STATUS +RecordFmpCapsuleStatusVariable ( + IN EFI_CAPSULE_HEADER *CapsuleHeader, + IN EFI_STATUS CapsuleStatus, + IN UINTN PayloadIndex, + IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader, + IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL, + IN CHAR16 *CapFileName OPTIONAL + ) +{ + EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader; + EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp; + EFI_STATUS Status; + UINT8 *CapsuleResultVariable; + UINTN CapsuleResultVariableSize; + CHAR16 *DevicePathStr; + UINTN DevicePathStrSize; + UINTN CapFileNameSize; + + DevicePathStr = NULL; + CapFileNameSize = sizeof (CHAR16); + + if (FmpDevicePath != NULL) { + DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE); + } + + if (DevicePathStr != NULL) { + DevicePathStrSize = StrSize (DevicePathStr); + } else { + DevicePathStrSize = sizeof (CHAR16); + } + + if (CapFileName != NULL) { + CapFileNameSize = StrSize (CapFileName); + } + + // + // Allocate room for CapsuleFileName. + // + CapsuleResultVariableSize = sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize + DevicePathStrSize; + + CapsuleResultVariable = AllocateZeroPool (CapsuleResultVariableSize); + if (CapsuleResultVariable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CapsuleResultVariableHeader = (VOID *)CapsuleResultVariable; + CapsuleResultVariableHeader->VariableTotalSize = (UINT32)CapsuleResultVariableSize; + CapsuleResultVariableHeader->Reserved = 0; + CopyGuid (&CapsuleResultVariableHeader->CapsuleGuid, &CapsuleHeader->CapsuleGuid); + ZeroMem (&CapsuleResultVariableHeader->CapsuleProcessed, sizeof (CapsuleResultVariableHeader->CapsuleProcessed)); + gRT->GetTime (&CapsuleResultVariableHeader->CapsuleProcessed, NULL); + CapsuleResultVariableHeader->CapsuleStatus = CapsuleStatus; + + CapsuleResultVariableFmp = (VOID *)(CapsuleResultVariable + sizeof (EFI_CAPSULE_RESULT_VARIABLE_HEADER)); + CapsuleResultVariableFmp->Version = 0x1; + CapsuleResultVariableFmp->PayloadIndex = (UINT8)PayloadIndex; + CapsuleResultVariableFmp->UpdateImageIndex = ImageHeader->UpdateImageIndex; + CopyGuid (&CapsuleResultVariableFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId); + + if (CapFileName != NULL) { + CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP), CapFileName, CapFileNameSize); + } + + if (DevicePathStr != NULL) { + CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof (EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize, DevicePathStr, DevicePathStrSize); + FreePool (DevicePathStr); + DevicePathStr = NULL; + } + + Status = EFI_SUCCESS; + if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) { + Status = WriteNewCapsuleResultVariable (CapsuleResultVariable, CapsuleResultVariableSize); + } + + FreePool (CapsuleResultVariable); + return Status; +} + +/** + Initialize CapsuleMax variables. + + @param[in] VariablePolicy The pointer of variable lock policy +**/ +VOID +InitCapsuleMaxVariable ( + EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy + ) +{ + EFI_STATUS Status; + UINTN Size; + CHAR16 CapsuleMaxStr[sizeof ("Capsule####")]; + + UnicodeSPrint ( + CapsuleMaxStr, + sizeof (CapsuleMaxStr), + L"Capsule%04x", + PcdGet16 (PcdCapsuleMax) + ); + + Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator + Status = gRT->SetVariable ( + L"CapsuleMax", + &gEfiCapsuleReportGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + Size, + CapsuleMaxStr + ); + if (!EFI_ERROR (Status)) { + // Lock it per UEFI spec. + LockVariable (gEfiCapsuleReportGuid, L"CapsuleMax", VariablePolicy); + } +} + +/** + Initialize CapsuleLast variables. + + @param[in] VariablePolicy The pointer of variable lock policy +**/ +VOID +InitCapsuleLastVariable ( + EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy + ) +{ + EFI_STATUS Status; + EFI_BOOT_MODE BootMode; + VOID *CapsuleResult; + UINTN Size; + CHAR16 CapsuleLastStr[sizeof ("Capsule####")]; + + BootMode = GetBootModeHob (); + if (BootMode == BOOT_ON_FLASH_UPDATE) { + Status = gRT->SetVariable ( + L"CapsuleLast", + &gEfiCapsuleReportGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 0, + NULL + ); + // Do not lock it because it will be updated later. + } else { + // + // Check if OS/APP cleared L"Capsule####" + // + ZeroMem (CapsuleLastStr, sizeof (CapsuleLastStr)); + Size = sizeof (L"Capsule####") - sizeof (CHAR16); // no zero terminator + Status = gRT->GetVariable ( + L"CapsuleLast", + &gEfiCapsuleReportGuid, + NULL, + &Size, + CapsuleLastStr + ); + if (!EFI_ERROR (Status)) { + // + // L"CapsuleLast" is got, check if data is there. + // + Status = GetVariable2 ( + CapsuleLastStr, + &gEfiCapsuleReportGuid, + (VOID **)&CapsuleResult, + NULL + ); + if (EFI_ERROR (Status)) { + // + // If no data, delete L"CapsuleLast" + // + Status = gRT->SetVariable ( + L"CapsuleLast", + &gEfiCapsuleReportGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 0, + NULL + ); + } else { + if (CapsuleResult != NULL) { + FreePool (CapsuleResult); + } + } + } + + // Lock it in normal boot path per UEFI spec. + LockVariable (gEfiCapsuleReportGuid, L"CapsuleLast", VariablePolicy); + } +} + +/** + Initialize capsule update variables. +**/ +VOID +InitCapsuleUpdateVariable ( + VOID + ) +{ + EFI_STATUS Status; + UINTN Index; + CHAR16 CapsuleVarName[30]; + CHAR16 *TempVarName; + + // + // Clear all the capsule variables CapsuleUpdateData, CapsuleUpdateData1, CapsuleUpdateData2... + // as early as possible which will avoid the next time boot after the capsule update + // will still into the capsule loop + // + StrCpyS (CapsuleVarName, sizeof (CapsuleVarName)/sizeof (CapsuleVarName[0]), EFI_CAPSULE_VARIABLE_NAME); + TempVarName = CapsuleVarName + StrLen (CapsuleVarName); + Index = 0; + while (TRUE) { + if (Index > 0) { + UnicodeValueToStringS ( + TempVarName, + sizeof (CapsuleVarName) - ((UINTN)TempVarName - (UINTN)CapsuleVarName), + 0, + Index, + 0 + ); + } + + Status = gRT->SetVariable ( + CapsuleVarName, + &gEfiCapsuleVendorGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + 0, + (VOID *)NULL + ); + if (EFI_ERROR (Status)) { + // + // There is no capsule variables, quit + // + break; + } + + Index++; + } +} + +/** + Initialize capsule relocation info variable. + + @param[in] VariablePolicy The pointer of variable lock policy +**/ +VOID +InitCapsuleRelocationInfo ( + EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy + ) +{ + CoDClearCapsuleRelocationInfo (); + + // + // Unlock Capsule On Disk relocation Info variable only when Capsule On Disk flag is enabled + // + if (!CoDCheckCapsuleOnDiskFlag ()) { + LockVariable (gEfiCapsuleVendorGuid, COD_RELOCATION_INFO_VAR_NAME, VariablePolicy); + } +} + +/** + Initialize capsule related variables. +**/ +VOID +InitCapsuleVariable ( + VOID + ) +{ + EFI_STATUS Status; + EDKII_VARIABLE_POLICY_PROTOCOL *VariablePolicy; + + // Locate the VariablePolicy protocol + Status = gBS->LocateProtocol (&gEdkiiVariablePolicyProtocolGuid, NULL, (VOID **)&VariablePolicy); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "DxeCapsuleReportLib %a - Could not locate VariablePolicy protocol! %r\n", __func__, Status)); + ASSERT_EFI_ERROR (Status); + } + + InitCapsuleUpdateVariable (); + InitCapsuleMaxVariable (VariablePolicy); + InitCapsuleLastVariable (VariablePolicy); + InitCapsuleRelocationInfo (VariablePolicy); + + // + // No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast" + // to check status and delete them. + // +} |
