mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/DxeCapsuleLibFmp: Add DxeCapsuleLibFmp instance.
This instance handles Microsoft UX capsule, UEFI defined FMP capsule. This instance should not assume any capsule image format. Cc: Feng Tian <feng.tian@intel.com> Cc: Star Zeng <star.zeng@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Chao Zhang <chao.b.zhang@intel.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com> Reviewed-by: Michael Kinney <michael.d.kinney@intel.com> Tested-by: Michael Kinney <michael.d.kinney@intel.com>
This commit is contained in:
parent
bf468a6ca0
commit
d2a160304e
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,80 @@
|
||||||
|
## @file
|
||||||
|
# Capsule library instance for DXE_DRIVER.
|
||||||
|
#
|
||||||
|
# Capsule library instance for DXE_DRIVER module types.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
# This program and the accompanying materials
|
||||||
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = DxeCapsuleLib
|
||||||
|
MODULE_UNI_FILE = DxeCapsuleLib.uni
|
||||||
|
FILE_GUID = 534E35DE-8EB3-47b3-A4E0-72A571E50733
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
LIBRARY_CLASS = CapsuleLib|DXE_DRIVER UEFI_APPLICATION
|
||||||
|
CONSTRUCTOR = DxeCapsuleLibConstructor
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
DxeCapsuleLib.c
|
||||||
|
DxeCapsuleProcessLib.c
|
||||||
|
DxeCapsuleReportLib.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
DxeServicesTableLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
DevicePathLib
|
||||||
|
ReportStatusCodeLib
|
||||||
|
PrintLib
|
||||||
|
HobLib
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES
|
||||||
|
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem ## CONSUMES
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEsrtManagementProtocolGuid ## CONSUMES
|
||||||
|
gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiSystemResourceTableGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiCapsuleReportGuid ## CONSUMES ## Variable
|
||||||
|
gEfiCapsuleVendorGuid ## CONSUMES ## Variable
|
||||||
|
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiVariableWriteArchProtocolGuid
|
|
@ -0,0 +1,22 @@
|
||||||
|
// /** @file
|
||||||
|
// Capsule library instance for DXE_DRIVER.
|
||||||
|
//
|
||||||
|
// Capsule library instance for DXE_DRIVER module types.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
//
|
||||||
|
// This program and the accompanying materials
|
||||||
|
// are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
// which accompanies this distribution. The full text of the license may be found at
|
||||||
|
// http://opensource.org/licenses/bsd-license.php
|
||||||
|
//
|
||||||
|
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
//
|
||||||
|
// **/
|
||||||
|
|
||||||
|
|
||||||
|
#string STR_MODULE_ABSTRACT #language en-US "Capsule Support Library"
|
||||||
|
|
||||||
|
#string STR_MODULE_DESCRIPTION #language en-US "Capsule library instance for DXE_DRIVER module types."
|
||||||
|
|
|
@ -0,0 +1,475 @@
|
||||||
|
/** @file
|
||||||
|
DXE capsule process.
|
||||||
|
|
||||||
|
Caution: This module requires additional review when modified.
|
||||||
|
This module will have external input - capsule image.
|
||||||
|
This external input must be validated carefully to avoid security issue like
|
||||||
|
buffer overflow, integer overflow.
|
||||||
|
|
||||||
|
ProcessCapsules(), ProcessTheseCapsules() will receive untrusted
|
||||||
|
input and do basic validation.
|
||||||
|
|
||||||
|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
#include <Protocol/EsrtManagement.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/ReportStatusCodeLib.h>
|
||||||
|
#include <Library/CapsuleLib.h>
|
||||||
|
|
||||||
|
#include <IndustryStandard/WindowsUxCapsule.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
|
||||||
|
|
||||||
|
@param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
|
||||||
|
|
||||||
|
@retval TRUE It is a system FMP.
|
||||||
|
@retval FALSE It is a device FMP.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsFmpCapsule (
|
||||||
|
IN EFI_CAPSULE_HEADER *CapsuleHeader
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Validate Fmp capsules layout.
|
||||||
|
|
||||||
|
Caution: This function may receive untrusted input.
|
||||||
|
|
||||||
|
This function assumes the caller validated the capsule by using
|
||||||
|
IsValidCapsuleHeader(), so that all fields in EFI_CAPSULE_HEADER are correct.
|
||||||
|
The capsule buffer size is CapsuleHeader->CapsuleImageSize.
|
||||||
|
|
||||||
|
This function validates the fields in EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER
|
||||||
|
and EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER.
|
||||||
|
|
||||||
|
This function need support nested FMP capsule.
|
||||||
|
|
||||||
|
@param[in] CapsuleHeader Points to a capsule header.
|
||||||
|
@param[out] EmbeddedDriverCount The EmbeddedDriverCount in the FMP capsule.
|
||||||
|
|
||||||
|
@retval EFI_SUCESS Input capsule is a correct FMP capsule.
|
||||||
|
@retval EFI_INVALID_PARAMETER Input capsule is not a correct FMP capsule.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
ValidateFmpCapsule (
|
||||||
|
IN EFI_CAPSULE_HEADER *CapsuleHeader,
|
||||||
|
OUT UINT16 *EmbeddedDriverCount OPTIONAL
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Validate if it is valid capsule header
|
||||||
|
|
||||||
|
This function assumes the caller provided correct CapsuleHeader pointer
|
||||||
|
and CapsuleSize.
|
||||||
|
|
||||||
|
This function validates the fields in EFI_CAPSULE_HEADER.
|
||||||
|
|
||||||
|
@param[in] CapsuleHeader Points to a capsule header.
|
||||||
|
@param[in] CapsuleSize Size of the whole capsule image.
|
||||||
|
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsValidCapsuleHeader (
|
||||||
|
IN EFI_CAPSULE_HEADER *CapsuleHeader,
|
||||||
|
IN UINT64 CapsuleSize
|
||||||
|
);
|
||||||
|
|
||||||
|
extern BOOLEAN mDxeCapsuleLibEndOfDxe;
|
||||||
|
extern BOOLEAN mAreAllImagesProcessed;
|
||||||
|
BOOLEAN mNeedReset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
This routine is called to process capsules.
|
||||||
|
|
||||||
|
Caution: This function may receive untrusted input.
|
||||||
|
|
||||||
|
Each individual capsule result is recorded in capsule record variable.
|
||||||
|
|
||||||
|
@param[in] NeedBlockDriver TRUE: Need skip the FMP capsules with non zero EmbeddedDriverCount.
|
||||||
|
FALSE: No need to skip any FMP capsules.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS There is no error when processing capsules.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
ProcessTheseCapsules (
|
||||||
|
IN BOOLEAN NeedBlockDriver
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_PEI_HOB_POINTERS HobPointer;
|
||||||
|
EFI_CAPSULE_HEADER *CapsuleHeader;
|
||||||
|
UINT32 Size;
|
||||||
|
UINT32 CapsuleNumber;
|
||||||
|
UINT32 CapsuleTotalNumber;
|
||||||
|
EFI_CAPSULE_TABLE *CapsuleTable;
|
||||||
|
UINT32 Index;
|
||||||
|
UINT32 CacheIndex;
|
||||||
|
UINT32 CacheNumber;
|
||||||
|
VOID **CapsulePtr;
|
||||||
|
VOID **CapsulePtrCache;
|
||||||
|
EFI_GUID *CapsuleGuidCache;
|
||||||
|
EFI_STATUS *CapsuleStatusArray;
|
||||||
|
BOOLEAN DisplayCapsuleExist;
|
||||||
|
ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
|
||||||
|
UINT16 EmbeddedDriverCount;
|
||||||
|
|
||||||
|
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));
|
||||||
|
|
||||||
|
CapsuleNumber = 0;
|
||||||
|
CapsuleTotalNumber = 0;
|
||||||
|
CacheIndex = 0;
|
||||||
|
CacheNumber = 0;
|
||||||
|
CapsulePtr = NULL;
|
||||||
|
CapsulePtrCache = NULL;
|
||||||
|
CapsuleGuidCache = NULL;
|
||||||
|
DisplayCapsuleExist = FALSE;
|
||||||
|
EsrtManagement = NULL;
|
||||||
|
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
//
|
||||||
|
// Find all capsule images from hob
|
||||||
|
//
|
||||||
|
HobPointer.Raw = GetHobList ();
|
||||||
|
while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
|
||||||
|
if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) {
|
||||||
|
HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid
|
||||||
|
} else {
|
||||||
|
CapsuleTotalNumber++;
|
||||||
|
}
|
||||||
|
HobPointer.Raw = GET_NEXT_HOB (HobPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CapsuleTotalNumber == 0) {
|
||||||
|
//
|
||||||
|
// We didn't find a hob, so had no errors.
|
||||||
|
//
|
||||||
|
DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update boot mode.\n"));
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init temp Capsule Data table.
|
||||||
|
//
|
||||||
|
CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
|
||||||
|
ASSERT (CapsulePtr != NULL);
|
||||||
|
if (CapsulePtr == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);
|
||||||
|
ASSERT (CapsulePtrCache != NULL);
|
||||||
|
if (CapsulePtrCache == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);
|
||||||
|
ASSERT (CapsuleGuidCache != NULL);
|
||||||
|
if (CapsuleGuidCache == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
CapsuleStatusArray = (EFI_STATUS *) AllocateZeroPool (sizeof (EFI_STATUS) * CapsuleTotalNumber);
|
||||||
|
ASSERT (CapsuleStatusArray != NULL);
|
||||||
|
if (CapsuleStatusArray == NULL) {
|
||||||
|
Status = EFI_OUT_OF_RESOURCES;
|
||||||
|
goto Done;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Find all capsule images from hob
|
||||||
|
//
|
||||||
|
HobPointer.Raw = GetHobList ();
|
||||||
|
while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
|
||||||
|
CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
|
||||||
|
HobPointer.Raw = GET_NEXT_HOB (HobPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install
|
||||||
|
// capsuleTable to configure table with EFI_CAPSULE_GUID
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating
|
||||||
|
// System to have information persist across a system reset. EFI System Table must
|
||||||
|
// point to an array of capsules that contains the same CapsuleGuid value. And agents
|
||||||
|
// searching for this type capsule will look in EFI System Table and search for the
|
||||||
|
// capsule's Guid and associated pointer to retrieve the data. Two steps below describes
|
||||||
|
// how to sorting the capsules by the unique guid and install the array to EFI System Table.
|
||||||
|
// Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an
|
||||||
|
// array for later sorting capsules by CapsuleGuid.
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < CapsuleTotalNumber; Index++) {
|
||||||
|
CapsuleStatusArray [Index] = EFI_UNSUPPORTED;
|
||||||
|
CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
|
||||||
|
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
|
||||||
|
//
|
||||||
|
// For each capsule, we compare it with known CapsuleGuid in the CacheArray.
|
||||||
|
// If already has the Guid, skip it. Whereas, record it in the CacheArray as
|
||||||
|
// an additional one.
|
||||||
|
//
|
||||||
|
CacheIndex = 0;
|
||||||
|
while (CacheIndex < CacheNumber) {
|
||||||
|
if (CompareGuid(&CapsuleGuidCache[CacheIndex],&CapsuleHeader->CapsuleGuid)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
CacheIndex++;
|
||||||
|
}
|
||||||
|
if (CacheIndex == CacheNumber) {
|
||||||
|
CopyMem(&CapsuleGuidCache[CacheNumber++],&CapsuleHeader->CapsuleGuid,sizeof(EFI_GUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Secondly, for each unique CapsuleGuid in CacheArray, gather all coalesced capsules
|
||||||
|
// whose guid is the same as it, and malloc memory for an array which preceding
|
||||||
|
// with UINT32. The array fills with entry point of capsules that have the same
|
||||||
|
// CapsuleGuid, and UINT32 represents the size of the array of capsules. Then install
|
||||||
|
// this array into EFI System Table, so that agents searching for this type capsule
|
||||||
|
// will look in EFI System Table and search for the capsule's Guid and associated
|
||||||
|
// pointer to retrieve the data.
|
||||||
|
//
|
||||||
|
CacheIndex = 0;
|
||||||
|
while (CacheIndex < CacheNumber) {
|
||||||
|
CapsuleNumber = 0;
|
||||||
|
for (Index = 0; Index < CapsuleTotalNumber; Index++) {
|
||||||
|
CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
|
||||||
|
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {
|
||||||
|
if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {
|
||||||
|
//
|
||||||
|
// Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.
|
||||||
|
//
|
||||||
|
CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;
|
||||||
|
//
|
||||||
|
// When a Capsule is listed in CapsulePtrCache, it will be reported in ConfigurationTable
|
||||||
|
// So, report the CapsuleStatus as "processed successfully".
|
||||||
|
//
|
||||||
|
CapsuleStatusArray [Index] = EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (CapsuleNumber != 0) {
|
||||||
|
Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);
|
||||||
|
CapsuleTable = AllocateRuntimePool (Size);
|
||||||
|
ASSERT (CapsuleTable != NULL);
|
||||||
|
if (CapsuleTable == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
CapsuleTable->CapsuleArrayNumber = CapsuleNumber;
|
||||||
|
CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));
|
||||||
|
Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
}
|
||||||
|
CacheIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdatingFirmware)));
|
||||||
|
|
||||||
|
//
|
||||||
|
// If Windows UX capsule exist, process it first
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < CapsuleTotalNumber; Index++) {
|
||||||
|
CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
|
||||||
|
if (CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
|
||||||
|
DEBUG ((DEBUG_INFO, "ProcessCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));
|
||||||
|
DisplayCapsuleExist = TRUE;
|
||||||
|
DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));
|
||||||
|
Status = ProcessCapsuleImage (CapsuleHeader);
|
||||||
|
DEBUG((DEBUG_INFO, "ProcessCapsuleImage (Ux) - %r\n", Status));
|
||||||
|
CapsuleStatusArray [Index] = Status;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DisplayCapsuleExist) {
|
||||||
|
//
|
||||||
|
// Display Capsule not found. Display the default string.
|
||||||
|
//
|
||||||
|
Print (L"Updating the firmware ......\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// All capsules left are recognized by platform.
|
||||||
|
//
|
||||||
|
for (Index = 0; Index < CapsuleTotalNumber; Index++) {
|
||||||
|
CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];
|
||||||
|
if (!CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {
|
||||||
|
//
|
||||||
|
// Call capsule library to process capsule image.
|
||||||
|
//
|
||||||
|
EmbeddedDriverCount = 0;
|
||||||
|
if (IsFmpCapsule(CapsuleHeader)) {
|
||||||
|
Status = ValidateFmpCapsule(CapsuleHeader, &EmbeddedDriverCount);
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
DEBUG((DEBUG_ERROR, "ValidateFmpCapsule failed. Ignore!\n"));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!NeedBlockDriver) || (EmbeddedDriverCount == 0)) {
|
||||||
|
DEBUG((DEBUG_INFO, "ProcessCapsuleImage - 0x%x\n", CapsuleHeader));
|
||||||
|
Status = ProcessCapsuleImage (CapsuleHeader);
|
||||||
|
CapsuleStatusArray [Index] = Status;
|
||||||
|
DEBUG((DEBUG_INFO, "ProcessCapsuleImage - %r\n", Status));
|
||||||
|
|
||||||
|
if (EFI_ERROR(Status)) {
|
||||||
|
REPORT_STATUS_CODE(EFI_ERROR_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareFailed)));
|
||||||
|
DEBUG ((DEBUG_ERROR, "Capsule process failed. reset the system!\n"));
|
||||||
|
Print (L"Firmware update failed...\r\n");
|
||||||
|
} else {
|
||||||
|
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareSuccess)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 ||
|
||||||
|
IsFmpCapsule(CapsuleHeader)) {
|
||||||
|
mNeedReset = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtManagement);
|
||||||
|
//
|
||||||
|
// Always sync ESRT Cache from FMP Instance
|
||||||
|
//
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
EsrtManagement->SyncEsrtFmp();
|
||||||
|
}
|
||||||
|
Status = EFI_SUCCESS;
|
||||||
|
|
||||||
|
Done:
|
||||||
|
//
|
||||||
|
// Free the allocated temp memory space.
|
||||||
|
//
|
||||||
|
if (CapsuleGuidCache != NULL) {
|
||||||
|
FreePool(CapsuleGuidCache);
|
||||||
|
}
|
||||||
|
if (CapsulePtrCache != NULL) {
|
||||||
|
FreePool(CapsulePtrCache);
|
||||||
|
}
|
||||||
|
if (CapsulePtr != NULL) {
|
||||||
|
FreePool(CapsulePtr);
|
||||||
|
}
|
||||||
|
|
||||||
|
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesEnd)));
|
||||||
|
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Do reset system.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DoResetSystem (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeResettingSystem)));
|
||||||
|
|
||||||
|
Print(L"Capsule Request Cold Reboot.\n");
|
||||||
|
DEBUG((DEBUG_INFO, "Capsule Request Cold Reboot."));
|
||||||
|
|
||||||
|
for (Index = 5; Index > 0; Index--) {
|
||||||
|
Print(L"\rResetting system in %d seconds ...", Index);
|
||||||
|
DEBUG((DEBUG_INFO, "\rResetting system in %d seconds ...", Index));
|
||||||
|
gBS->Stall(1000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
|
||||||
|
|
||||||
|
CpuDeadLoop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
This routine is called to process capsules.
|
||||||
|
|
||||||
|
Caution: This function may receive untrusted input.
|
||||||
|
|
||||||
|
The capsules reported in EFI_HOB_UEFI_CAPSULE are processed.
|
||||||
|
If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.
|
||||||
|
|
||||||
|
This routine should be called twice in BDS.
|
||||||
|
1) The first call must be before EndOfDxe. The system capsules is processed.
|
||||||
|
If device capsule FMP protocols are exposted at this time and device FMP
|
||||||
|
capsule has zero EmbeddedDriverCount, the device capsules are processed.
|
||||||
|
Each individual capsule result is recorded in capsule record variable.
|
||||||
|
System may reset in this function, if reset is required by capsule and
|
||||||
|
all capsules are processed.
|
||||||
|
If not all capsules are processed, reset will be defered to second call.
|
||||||
|
|
||||||
|
2) The second call must be after EndOfDxe and after ConnectAll, so that all
|
||||||
|
device capsule FMP protocols are exposed.
|
||||||
|
The system capsules are skipped. If the device capsules are NOT processed
|
||||||
|
in first call, they are processed here.
|
||||||
|
Each individual capsule result is recorded in capsule record variable.
|
||||||
|
System may reset in this function, if reset is required by capsule
|
||||||
|
processed in first call and second call.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS There is no error when processing capsules.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ProcessCapsules (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
if (!mDxeCapsuleLibEndOfDxe) {
|
||||||
|
//
|
||||||
|
// Initialize mAreAllImagesProcessed to be TRUE.
|
||||||
|
//
|
||||||
|
// It will be updated to FALSE in ProcessTheseCapsules()->ProcessCapsuleImage(),
|
||||||
|
// if there is any FMP image in any FMP capsule not processed.
|
||||||
|
//
|
||||||
|
mAreAllImagesProcessed = TRUE;
|
||||||
|
|
||||||
|
Status = ProcessTheseCapsules(TRUE);
|
||||||
|
//
|
||||||
|
// Reboot System if and only if all capsule processed.
|
||||||
|
// If not, defer reset to 2nd process.
|
||||||
|
//
|
||||||
|
if (mNeedReset && mAreAllImagesProcessed) {
|
||||||
|
DoResetSystem();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Status = ProcessTheseCapsules(FALSE);
|
||||||
|
//
|
||||||
|
// Reboot System if required after all capsule processed
|
||||||
|
//
|
||||||
|
if (mNeedReset) {
|
||||||
|
DoResetSystem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
/** @file
|
||||||
|
DXE capsule process.
|
||||||
|
Dummy function for runtime module, because CapsuleDxeRuntime
|
||||||
|
does not need call ProcessCapsules().
|
||||||
|
|
||||||
|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
#include <Library/CapsuleLib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
This routine is called to process capsules.
|
||||||
|
|
||||||
|
Caution: This function may receive untrusted input.
|
||||||
|
|
||||||
|
The capsules reported in EFI_HOB_UEFI_CAPSULE are processed.
|
||||||
|
If there is no EFI_HOB_UEFI_CAPSULE, this routine does nothing.
|
||||||
|
|
||||||
|
This routine should be called twice in BDS.
|
||||||
|
1) The first call must be before EndOfDxe. The system capsules is processed.
|
||||||
|
If device capsule FMP protocols are exposted at this time and device FMP
|
||||||
|
capsule has zero EmbeddedDriverCount, the device capsules are processed.
|
||||||
|
Each individual capsule result is recorded in capsule record variable.
|
||||||
|
System may reset in this function, if reset is required by capsule and
|
||||||
|
all capsules are processed.
|
||||||
|
If not all capsules are processed, reset will be defered to second call.
|
||||||
|
|
||||||
|
2) The second call must be after EndOfDxe and after ConnectAll, so that all
|
||||||
|
device capsule FMP protocols are exposed.
|
||||||
|
The system capsules are skipped. If the device capsules are NOT processed
|
||||||
|
in first call, they are processed here.
|
||||||
|
Each individual capsule result is recorded in capsule record variable.
|
||||||
|
System may reset in this function, if reset is required by capsule
|
||||||
|
processed in first call and second call.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS There is no error when processing capsules.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.
|
||||||
|
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
ProcessCapsules (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
|
@ -0,0 +1,489 @@
|
||||||
|
/** @file
|
||||||
|
DXE capsule report related function.
|
||||||
|
|
||||||
|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
#include <Protocol/FirmwareManagement.h>
|
||||||
|
#include <Protocol/VariableLock.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/CapsuleLib.h>
|
||||||
|
|
||||||
|
#include <IndustryStandard/WindowsUxCapsule.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EFI_CAPSULE_RESULT_VARIABLE_HEADER CapsuleResultHeader;
|
||||||
|
EFI_CAPSULE_RESULT_VARIABLE_FMP CapsuleResultFmp;
|
||||||
|
} CAPSULE_RESULT_VARIABLE_CACHE;
|
||||||
|
|
||||||
|
#define CAPSULE_RESULT_VARIABLE_CACHE_COUNT 0x10
|
||||||
|
|
||||||
|
CAPSULE_RESULT_VARIABLE_CACHE *mCapsuleResultVariableCache;
|
||||||
|
UINTN mCapsuleResultVariableCacheMaxCount;
|
||||||
|
UINTN mCapsuleResultVariableCacheCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if this FMP capsule is processed.
|
||||||
|
|
||||||
|
@param[in] CapsuleHeader The capsule image header
|
||||||
|
@param[in] PayloadIndex FMP payload index
|
||||||
|
@param[in] ImageHeader FMP image header
|
||||||
|
|
||||||
|
@retval TRUE This FMP capsule is processed.
|
||||||
|
@retval FALSE This FMP capsule is not processed.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsFmpCapsuleProcessed (
|
||||||
|
IN EFI_CAPSULE_HEADER *CapsuleHeader,
|
||||||
|
IN UINTN PayloadIndex,
|
||||||
|
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResult;
|
||||||
|
EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultFmp;
|
||||||
|
|
||||||
|
for (Index = 0; Index < mCapsuleResultVariableCacheCount; Index++) {
|
||||||
|
//
|
||||||
|
// Check
|
||||||
|
//
|
||||||
|
CapsuleResult = &mCapsuleResultVariableCache[Index].CapsuleResultHeader;
|
||||||
|
if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER)) {
|
||||||
|
if (CompareGuid(&CapsuleResult->CapsuleGuid, &gEfiFmpCapsuleGuid)) {
|
||||||
|
if (CapsuleResult->VariableTotalSize >= sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)) {
|
||||||
|
CapsuleResultFmp = (EFI_CAPSULE_RESULT_VARIABLE_FMP *)(CapsuleResult + 1);
|
||||||
|
if (CompareGuid(&CapsuleResultFmp->UpdateImageTypeId, &ImageHeader->UpdateImageTypeId) &&
|
||||||
|
(CapsuleResultFmp->UpdateImageIndex == ImageHeader->UpdateImageIndex) &&
|
||||||
|
(CapsuleResultFmp->PayloadIndex == PayloadIndex) ) {
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Write a new capsule status variable cache.
|
||||||
|
|
||||||
|
@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 cached.
|
||||||
|
@retval EFI_OUT_OF_RESOURCES No resource to cache the capsule status variable.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
WriteNewCapsuleResultVariableCache (
|
||||||
|
IN VOID *CapsuleResult,
|
||||||
|
IN UINTN CapsuleResultSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (CapsuleResultSize > sizeof(CAPSULE_RESULT_VARIABLE_CACHE)) {
|
||||||
|
CapsuleResultSize = sizeof(CAPSULE_RESULT_VARIABLE_CACHE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mCapsuleResultVariableCacheCount == mCapsuleResultVariableCacheMaxCount) {
|
||||||
|
mCapsuleResultVariableCache = ReallocatePool(
|
||||||
|
mCapsuleResultVariableCacheMaxCount * sizeof(CAPSULE_RESULT_VARIABLE_CACHE),
|
||||||
|
(mCapsuleResultVariableCacheMaxCount + CAPSULE_RESULT_VARIABLE_CACHE_COUNT) * sizeof(CAPSULE_RESULT_VARIABLE_CACHE),
|
||||||
|
mCapsuleResultVariableCache
|
||||||
|
);
|
||||||
|
if (mCapsuleResultVariableCache == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
mCapsuleResultVariableCacheMaxCount += CAPSULE_RESULT_VARIABLE_CACHE_COUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(mCapsuleResultVariableCacheCount < mCapsuleResultVariableCacheMaxCount);
|
||||||
|
ASSERT(mCapsuleResultVariableCache != NULL);
|
||||||
|
CopyMem(
|
||||||
|
&mCapsuleResultVariableCache[mCapsuleResultVariableCacheCount],
|
||||||
|
CapsuleResult,
|
||||||
|
CapsuleResultSize
|
||||||
|
);
|
||||||
|
mCapsuleResultVariableCacheCount++;
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get a new capsule status variable index.
|
||||||
|
|
||||||
|
@return A new capsule status variable index.
|
||||||
|
@retval -1 No new capsule status variable index.
|
||||||
|
**/
|
||||||
|
INTN
|
||||||
|
GetNewCapsuleResultIndex (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
INTN CurrentIndex;
|
||||||
|
|
||||||
|
CurrentIndex = GetCurrentCapsuleLastIndex();
|
||||||
|
if (CurrentIndex >= PcdGet16(PcdCapsuleMax)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CurrentIndex + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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));
|
||||||
|
if (CapsuleResultIndex == -1) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
CopyGuid (&CapsuleResultVariable.CapsuleGuid, &CapsuleHeader->CapsuleGuid);
|
||||||
|
ZeroMem(&CapsuleResultVariable.CapsuleProcessed, sizeof(CapsuleResultVariable.CapsuleProcessed));
|
||||||
|
gRT->GetTime(&CapsuleResultVariable.CapsuleProcessed, NULL);
|
||||||
|
CapsuleResultVariable.CapsuleStatus = CapsuleStatus;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save Local Cache
|
||||||
|
//
|
||||||
|
Status = WriteNewCapsuleResultVariableCache(&CapsuleResultVariable, sizeof(CapsuleResultVariable));
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
@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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT8 CapsuleResultVariable[sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP)];
|
||||||
|
EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader;
|
||||||
|
EFI_CAPSULE_RESULT_VARIABLE_FMP *CapsuleResultVariableFmp;
|
||||||
|
EFI_STATUS Status;
|
||||||
|
|
||||||
|
CapsuleResultVariableHeader = (VOID *)&CapsuleResultVariable[0];
|
||||||
|
CapsuleResultVariableHeader->VariableTotalSize = sizeof(CapsuleResultVariable);
|
||||||
|
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);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Save Local Cache
|
||||||
|
//
|
||||||
|
Status = WriteNewCapsuleResultVariableCache(&CapsuleResultVariable, sizeof(CapsuleResultVariable));
|
||||||
|
|
||||||
|
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_PERSIST_ACROSS_RESET) != 0) {
|
||||||
|
Status = WriteNewCapsuleResultVariable(&CapsuleResultVariable, sizeof(CapsuleResultVariable));
|
||||||
|
}
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize CapsuleMax variables.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
InitCapsuleMaxVariable (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
UINTN Size;
|
||||||
|
CHAR16 CapsuleMaxStr[sizeof("Capsule####")];
|
||||||
|
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
|
||||||
|
|
||||||
|
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.
|
||||||
|
Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
Status = VariableLock->RequestToLock(VariableLock, L"CapsuleMax", &gEfiCapsuleReportGuid);
|
||||||
|
ASSERT_EFI_ERROR(Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize CapsuleLast variables.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
InitCapsuleLastVariable (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_BOOT_MODE BootMode;
|
||||||
|
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
|
||||||
|
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
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lock it in normal boot path per UEFI spec.
|
||||||
|
Status = gBS->LocateProtocol(&gEdkiiVariableLockProtocolGuid, NULL, (VOID **)&VariableLock);
|
||||||
|
if (!EFI_ERROR(Status)) {
|
||||||
|
Status = VariableLock->RequestToLock(VariableLock, L"CapsuleLast", &gEfiCapsuleReportGuid);
|
||||||
|
ASSERT_EFI_ERROR(Status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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) {
|
||||||
|
UnicodeValueToString (TempVarName, 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 related variables.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
InitCapsuleVariable (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
InitCapsuleUpdateVariable();
|
||||||
|
InitCapsuleMaxVariable();
|
||||||
|
InitCapsuleLastVariable();
|
||||||
|
//
|
||||||
|
// No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"
|
||||||
|
// to check status and delete them.
|
||||||
|
//
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/** @file
|
||||||
|
DXE capsule report related function.
|
||||||
|
Dummy function for runtime module, because CapsuleDxeRuntime
|
||||||
|
does not need record capsule status variable.
|
||||||
|
|
||||||
|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
#include <Protocol/FirmwareManagement.h>
|
||||||
|
#include <Guid/FmpCapsule.h>
|
||||||
|
#include <Library/CapsuleLib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
Check if this FMP capsule is processed.
|
||||||
|
|
||||||
|
@param[in] CapsuleHeader The capsule image header
|
||||||
|
@param[in] PayloadIndex FMP payload index
|
||||||
|
@param[in] ImageHeader FMP image header
|
||||||
|
|
||||||
|
@retval TRUE This FMP capsule is processed.
|
||||||
|
@retval FALSE This FMP capsule is not processed.
|
||||||
|
**/
|
||||||
|
BOOLEAN
|
||||||
|
IsFmpCapsuleProcessed (
|
||||||
|
IN EFI_CAPSULE_HEADER *CapsuleHeader,
|
||||||
|
IN UINTN PayloadIndex,
|
||||||
|
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
|
||||||
|
@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
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Initialize capsule related variables.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
InitCapsuleVariable (
|
||||||
|
VOID
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
|
@ -0,0 +1,112 @@
|
||||||
|
/** @file
|
||||||
|
Capsule library runtime support.
|
||||||
|
|
||||||
|
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiDxe.h>
|
||||||
|
|
||||||
|
#include <Guid/FmpCapsule.h>
|
||||||
|
#include <Guid/SystemResourceTable.h>
|
||||||
|
#include <Guid/EventGroup.h>
|
||||||
|
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DxeServicesTableLib.h>
|
||||||
|
#include <Library/UefiBootServicesTableLib.h>
|
||||||
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
|
||||||
|
extern EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable;
|
||||||
|
extern BOOLEAN mIsVirtualAddrConverted;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Convert EsrtTable physical address to virtual address.
|
||||||
|
|
||||||
|
@param[in] Event Event whose notification function is being invoked.
|
||||||
|
@param[in] Context The pointer to the notification function's context, which
|
||||||
|
is implementation-dependent.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
DxeCapsuleLibVirtualAddressChangeEvent (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
EFI_CONFIGURATION_TABLE *ConfigEntry;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get Esrt table first
|
||||||
|
//
|
||||||
|
ConfigEntry = gST->ConfigurationTable;
|
||||||
|
for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
|
||||||
|
if (CompareGuid(&gEfiSystemResourceTableGuid, &ConfigEntry->VendorGuid)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ConfigEntry++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// If no Esrt table installed in Configure Table
|
||||||
|
//
|
||||||
|
if (Index < gST->NumberOfTableEntries) {
|
||||||
|
//
|
||||||
|
// Search Esrt to check given capsule is qualified
|
||||||
|
//
|
||||||
|
mEsrtTable = (EFI_SYSTEM_RESOURCE_TABLE *) ConfigEntry->VendorTable;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Update protocol pointer to Esrt Table.
|
||||||
|
//
|
||||||
|
gRT->ConvertPointer (0x00, (VOID**) &(mEsrtTable));
|
||||||
|
}
|
||||||
|
|
||||||
|
mIsVirtualAddrConverted = TRUE;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
The constructor function hook VirtualAddressChange event to use ESRT table as capsule routing table.
|
||||||
|
|
||||||
|
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||||
|
@param SystemTable A pointer to the EFI System Table.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The constructor successfully .
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
DxeRuntimeCapsuleLibConstructor (
|
||||||
|
IN EFI_HANDLE ImageHandle,
|
||||||
|
IN EFI_SYSTEM_TABLE *SystemTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_STATUS Status;
|
||||||
|
EFI_EVENT Event;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Make sure we can handle virtual address changes.
|
||||||
|
//
|
||||||
|
Event = NULL;
|
||||||
|
Status = gBS->CreateEventEx (
|
||||||
|
EVT_NOTIFY_SIGNAL,
|
||||||
|
TPL_NOTIFY,
|
||||||
|
DxeCapsuleLibVirtualAddressChangeEvent,
|
||||||
|
NULL,
|
||||||
|
&gEfiEventVirtualAddressChangeGuid,
|
||||||
|
&Event
|
||||||
|
);
|
||||||
|
ASSERT_EFI_ERROR (Status);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
## @file
|
||||||
|
# Capsule library instance for DXE_RUNTIME_DRIVER.
|
||||||
|
#
|
||||||
|
# Capsule library instance for DXE_RUNTIME_DRIVER module types.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
# This program and the accompanying materials
|
||||||
|
# are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
# which accompanies this distribution. The full text of the license may be found at
|
||||||
|
# http://opensource.org/licenses/bsd-license.php
|
||||||
|
#
|
||||||
|
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 0x00010005
|
||||||
|
BASE_NAME = DxeRuntimeCapsuleLib
|
||||||
|
MODULE_UNI_FILE = DxeRuntimeCapsuleLib.uni
|
||||||
|
FILE_GUID = 19BE1E4B-1A9A-44c1-8F12-32DD0470516A
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
LIBRARY_CLASS = CapsuleLib|DXE_RUNTIME_DRIVER
|
||||||
|
CONSTRUCTOR = DxeCapsuleLibConstructor
|
||||||
|
CONSTRUCTOR = DxeRuntimeCapsuleLibConstructor
|
||||||
|
|
||||||
|
#
|
||||||
|
# The following information is for reference only and not required by the build tools.
|
||||||
|
#
|
||||||
|
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||||
|
#
|
||||||
|
|
||||||
|
[Sources]
|
||||||
|
DxeCapsuleLib.c
|
||||||
|
DxeCapsuleProcessLibNull.c
|
||||||
|
DxeCapsuleReportLibNull.c
|
||||||
|
DxeCapsuleRuntime.c
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
BaseLib
|
||||||
|
BaseMemoryLib
|
||||||
|
DebugLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
DxeServicesTableLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
DevicePathLib
|
||||||
|
ReportStatusCodeLib
|
||||||
|
PrintLib
|
||||||
|
HobLib
|
||||||
|
|
||||||
|
[Pcd]
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdSystemRebootAfterCapsuleProcessFlag ## CONSUMES
|
||||||
|
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdStatusCodeSubClassCapsule ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesBegin ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeProcessCapsulesEnd ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdatingFirmware ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed ## CONSUMES
|
||||||
|
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem ## CONSUMES
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEsrtManagementProtocolGuid ## CONSUMES
|
||||||
|
gEfiFirmwareManagementProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gWindowsUxCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiSystemResourceTableGuid ## SOMETIMES_CONSUMES ## GUID
|
||||||
|
gEfiCapsuleReportGuid ## CONSUMES ## Variable
|
||||||
|
gEfiCapsuleVendorGuid ## CONSUMES ## Variable
|
||||||
|
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
|
||||||
|
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
gEfiVariableWriteArchProtocolGuid
|
|
@ -0,0 +1,22 @@
|
||||||
|
// /** @file
|
||||||
|
// Capsule library instance for DXE_RUNTIME_DRIVER.
|
||||||
|
//
|
||||||
|
// Capsule library instance for DXE_RUNTIME_DRIVER module types.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
|
||||||
|
//
|
||||||
|
// This program and the accompanying materials
|
||||||
|
// are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
// which accompanies this distribution. The full text of the license may be found at
|
||||||
|
// http://opensource.org/licenses/bsd-license.php
|
||||||
|
//
|
||||||
|
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
//
|
||||||
|
// **/
|
||||||
|
|
||||||
|
|
||||||
|
#string STR_MODULE_ABSTRACT #language en-US "Capsule Support Library"
|
||||||
|
|
||||||
|
#string STR_MODULE_DESCRIPTION #language en-US "Capsule library instance for DXE_RUNTIME_DRIVER module types."
|
||||||
|
|
Loading…
Reference in New Issue