MdeModulePkg: Add Capsule On Disk APIs into CapsuleLib.

REF: https://github.com/tianocore/tianocore.github.io/wiki/
UEFI-Capsule-on-Disk-Introducation

CoDCheckCapsuleOnDiskFlag() is to check if CapsuleOnDisk flag in
"OsIndications" Variable is enabled. It is used to indicate whether
capsule on disk is provisioned in normal boot path.

CoDClearCapsuleOnDiskFlag() is to to clear CapsuleOnDisk flags,
including "OsIndications" and "BootNext" variable.

CoDRelocateCapsule() is to relocate the capsules from EFI system
partition. Depends on PcdCapsuleInRamSupport, there are two solutions
to relocate the capsule on disk images:
When Capsule In Ram is supported, the Capsule On Disk images are
relocated into memory, and call UpdateCapsule() service to deliver
the capsules.
When Capsule In Ram is not supported, the Capsule On Disk images are
relocated into a temp file which will be stored in root directory on
a platform specific storage device. CapsuleOnDiskLoadPei PEIM will
retrieve the capsules from the relocation temp file and report
capsule hobs for them.

CoDRemoveTempFile() is to remove the relocation temp file in the next
boot after capsules are processed.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Chao B Zhang <chao.b.zhang@intel.com>
Signed-off-by: Wei6 Xu <wei6.xu@intel.com>
Reviewed-by: Chao B Zhang <chao.b.zhang@intel.com>
Acked-by: Hao A Wu <hao.a.wu@intel.com>
This commit is contained in:
Wei6 Xu 2019-06-24 14:52:31 +08:00 committed by Zhang, Chao B
parent e761d18f01
commit 28889a7898
10 changed files with 2451 additions and 30 deletions

View File

@ -2,7 +2,7 @@
This library class defines a set of interfaces for how to process capsule image updates.
Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -10,6 +10,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#ifndef __CAPSULE_LIB_H__
#define __CAPSULE_LIB_H__
//
// BOOLEAN Variable to indicate whether system is in the capsule on disk state.
//
#define COD_RELOCATION_INFO_VAR_NAME L"CodRelocationInfo"
/**
The firmware checks whether the capsule image is supported
by the CapsuleGuid in CapsuleHeader or if there is other specific information in
@ -81,4 +86,75 @@ ProcessCapsules (
VOID
);
/**
This routine is called to check if CapsuleOnDisk flag in OsIndications Variable
is enabled.
@retval TRUE Flag is enabled
@retval FALSE Flag is not enabled
**/
BOOLEAN
EFIAPI
CoDCheckCapsuleOnDiskFlag(
VOID
);
/**
This routine is called to clear CapsuleOnDisk flags including OsIndications and BootNext variable
@retval EFI_SUCCESS All Capsule On Disk flags are cleared
**/
EFI_STATUS
EFIAPI
CoDClearCapsuleOnDiskFlag(
VOID
);
/**
Relocate Capsule on Disk from EFI system partition.
Two solution to deliver Capsule On Disk:
Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Disk to memory and call UpdateCapsule().
Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On Disk to a platform-specific NV storage
device with BlockIo protocol.
Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
Function will stall 100ms between each retry.
Side Effects:
Capsule Delivery Supported Flag in OsIndication variable and BootNext variable will be cleared.
Solution B: Content corruption. Block IO write directly touches low level write. Orignal partitions, file
systems of the relocation device will be corrupted.
@param[in] MaxRetry Max Connection Retry. Stall 100ms between each connection try to ensure
devices like USB can get enumerated. Input 0 means no retry.
@retval EFI_SUCCESS Capsule on Disk images are successfully relocated.
**/
EFI_STATUS
EFIAPI
CoDRelocateCapsule(
UINTN MaxRetry
);
/**
Remove the temp file from the root of EFI System Partition.
Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
Function will stall 100ms between each retry.
@param[in] MaxRetry Max Connection Retry. Stall 100ms between each connection try to ensure
devices like USB can get enumerated. Input 0 means no retry.
@retval EFI_SUCCESS Remove the temp file successfully.
**/
EFI_STATUS
EFIAPI
CoDRemoveTempFile (
UINTN MaxRetry
);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,75 @@
/** @file
Defines several datastructures used by Capsule On Disk feature.
They are mainly used for FAT files.
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _CAPSULES_ON_DISK_H_
#define _CAPSULES_ON_DISK_H_
#include <Uefi.h>
#include <Pi/PiMultiPhase.h>
#include <Library/UefiLib.h>
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiRuntimeLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/FileHandleLib.h>
#include <Library/CapsuleLib.h>
#include <Library/DevicePathLib.h>
#include <Library/PrintLib.h>
#include <Library/UefiBootManagerLib.h>
#include <Protocol/SimpleFileSystem.h>
#include <Protocol/DiskIo.h>
#include <Protocol/BlockIo.h>
#include <Guid/CapsuleVendor.h>
#include <Guid/FileInfo.h>
#include <Guid/GlobalVariable.h>
//
// This data structure is the part of FILE_INFO_ENTRY
//
#define FILE_INFO_SIGNATURE SIGNATURE_32 ('F', 'L', 'I', 'F')
//
// LoadOptionNumber of the boot option where the capsules is relocated.
//
#define COD_RELOCATION_LOAD_OPTION_VAR_NAME L"CodRelocationLoadOption"
//
// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)
//
#define MAX_FILE_NAME_SIZE 522
#define MAX_FILE_NAME_LEN (MAX_FILE_NAME_SIZE / sizeof(CHAR16))
#define MAX_FILE_INFO_LEN (OFFSET_OF(EFI_FILE_INFO, FileName) + MAX_FILE_NAME_LEN)
typedef struct {
UINTN Signature;
LIST_ENTRY Link; /// Linked list members.
EFI_FILE_INFO *FileInfo; /// Pointer to the FileInfo struct for this file or NULL.
CHAR16 *FileNameFirstPart; /// Text to the left of right-most period in the file name. String is capitialized
CHAR16 *FileNameSecondPart; /// Text to the right of right-most period in the file name.String is capitialized. Maybe NULL
} FILE_INFO_ENTRY;
typedef struct {
//
// image address.
//
VOID *ImageAddress;
//
// The file info of the image comes from.
// if FileInfo == NULL. means image does not come from file
//
EFI_FILE_INFO *FileInfo;
} IMAGE_INFO;
#endif // _CAPSULES_ON_DISK_H_

View File

@ -10,7 +10,7 @@
ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and
performs basic validation.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -80,6 +80,7 @@ RecordCapsuleStatusVariable (
@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.
@ -90,7 +91,8 @@ RecordFmpCapsuleStatusVariable (
IN EFI_STATUS CapsuleStatus,
IN UINTN PayloadIndex,
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL
IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OPTIONAL
IN CHAR16 *CapFileName OPTIONAL
);
/**
@ -109,6 +111,22 @@ UpdateImageProgress (
IN UINTN Completion
);
/**
Return if this capsule is a capsule name capsule, based upon CapsuleHeader.
@param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
@retval TRUE It is a capsule name capsule.
@retval FALSE It is not a capsule name capsule.
**/
BOOLEAN
IsCapsuleNameCapsule (
IN EFI_CAPSULE_HEADER *CapsuleHeader
)
{
return CompareGuid (&CapsuleHeader->CapsuleGuid, &gEdkiiCapsuleOnDiskNameGuid);
}
/**
Return if this CapsuleGuid is a FMP capsule GUID or not.
@ -1034,11 +1052,12 @@ StartFmpImage (
/**
Record FMP capsule status.
@param[in] Handle A FMP handle.
@param[in] Handle A FMP handle.
@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] CapFileName Capsule file name
**/
VOID
RecordFmpCapsuleStatus (
@ -1046,7 +1065,8 @@ RecordFmpCapsuleStatus (
IN EFI_CAPSULE_HEADER *CapsuleHeader,
IN EFI_STATUS CapsuleStatus,
IN UINTN PayloadIndex,
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
IN CHAR16 *CapFileName OPTIONAL
)
{
EFI_STATUS Status;
@ -1070,7 +1090,8 @@ RecordFmpCapsuleStatus (
CapsuleStatus,
PayloadIndex,
ImageHeader,
FmpDevicePath
FmpDevicePath,
CapFileName
);
//
@ -1115,6 +1136,7 @@ RecordFmpCapsuleStatus (
This function need support nested FMP capsule.
@param[in] CapsuleHeader Points to a capsule header.
@param[in] CapFileName Capsule file name.
@param[out] ResetRequired Indicates whether reset is required or not.
@retval EFI_SUCESS Process Capsule Image successfully.
@ -1126,6 +1148,7 @@ RecordFmpCapsuleStatus (
EFI_STATUS
ProcessFmpCapsuleImage (
IN EFI_CAPSULE_HEADER *CapsuleHeader,
IN CHAR16 *CapFileName, OPTIONAL
OUT BOOLEAN *ResetRequired OPTIONAL
)
{
@ -1145,7 +1168,7 @@ ProcessFmpCapsuleImage (
BOOLEAN Abort;
if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {
return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);
return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName, ResetRequired);
}
NotReady = FALSE;
@ -1227,7 +1250,8 @@ ProcessFmpCapsuleImage (
CapsuleHeader,
EFI_NOT_READY,
Index - FmpCapsuleHeader->EmbeddedDriverCount,
ImageHeader
ImageHeader,
CapFileName
);
continue;
}
@ -1239,7 +1263,8 @@ ProcessFmpCapsuleImage (
CapsuleHeader,
EFI_ABORTED,
Index - FmpCapsuleHeader->EmbeddedDriverCount,
ImageHeader
ImageHeader,
CapFileName
);
continue;
}
@ -1262,7 +1287,8 @@ ProcessFmpCapsuleImage (
CapsuleHeader,
Status,
Index - FmpCapsuleHeader->EmbeddedDriverCount,
ImageHeader
ImageHeader,
CapFileName
);
}
if (HandleBuffer != NULL) {
@ -1414,6 +1440,13 @@ SupportCapsuleImage (
return EFI_SUCCESS;
}
//
// Check capsule file name capsule
//
if (IsCapsuleNameCapsule(CapsuleHeader)) {
return EFI_SUCCESS;
}
if (IsFmpCapsule(CapsuleHeader)) {
//
// Fake capsule header is valid case in QueryCapsuleCpapbilities().
@ -1436,6 +1469,7 @@ SupportCapsuleImage (
Caution: This function may receive untrusted input.
@param[in] CapsuleHeader Points to a capsule header.
@param[in] CapFileName Capsule file name.
@param[out] ResetRequired Indicates whether reset is required or not.
@retval EFI_SUCESS Process Capsule Image successfully.
@ -1447,6 +1481,7 @@ EFI_STATUS
EFIAPI
ProcessThisCapsuleImage (
IN EFI_CAPSULE_HEADER *CapsuleHeader,
IN CHAR16 *CapFileName, OPTIONAL
OUT BOOLEAN *ResetRequired OPTIONAL
)
{
@ -1484,7 +1519,7 @@ ProcessThisCapsuleImage (
// Process EFI FMP Capsule
//
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));
Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);
Status = ProcessFmpCapsuleImage(CapsuleHeader, CapFileName, ResetRequired);
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));
return Status;
@ -1511,7 +1546,7 @@ ProcessCapsuleImage (
IN EFI_CAPSULE_HEADER *CapsuleHeader
)
{
return ProcessThisCapsuleImage (CapsuleHeader, NULL);
return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL);
}
/**

View File

@ -3,7 +3,7 @@
#
# Capsule library instance for DXE_DRIVER module types.
#
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@ -29,6 +29,8 @@
DxeCapsuleLib.c
DxeCapsuleProcessLib.c
DxeCapsuleReportLib.c
CapsuleOnDisk.c
CapsuleOnDisk.h
[Packages]
MdePkg/MdePkg.dec
@ -47,6 +49,8 @@
HobLib
BmpSupportLib
DisplayUpdateProgressLib
FileHandleLib
UefiBootManagerLib
[Pcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleMax ## CONSUMES
@ -59,12 +63,19 @@
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareSuccess ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeUpdateFirmwareFailed ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleStatusCodeResettingSystem ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleInRamSupport ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCapsuleOnDiskSupport ## CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCodRelocationDevPath ## SOMETIMES_CONSUMES
gEfiMdeModulePkgTokenSpaceGuid.PcdCoDRelocationFileName ## CONSUMES
[Protocols]
gEsrtManagementProtocolGuid ## CONSUMES
gEfiFirmwareManagementProtocolGuid ## CONSUMES
gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiFirmwareManagementProgressProtocolGuid ## SOMETIMES_CONSUMES
gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
gEfiBlockIoProtocolGuid ## CONSUMES
gEfiDiskIoProtocolGuid ## CONSUMES
[Guids]
gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
@ -74,6 +85,14 @@
gEfiCapsuleReportGuid
gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variable:L"CapsuleUpdateData"
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
gEfiPartTypeSystemPartGuid ## SOMETIMES_CONSUMES
gEfiCapsuleVendorGuid ## SOMETIMES_CONSUMES ## Variable:L"CodRelocationInfo"
## SOMETIMES_CONSUMES ## Variable:L"OsIndications"
## SOMETIMES_PRODUCES ## Variable:L"OsIndications"
## SOMETIMES_CONSUMES ## Variable:L"BootNext"
## SOMETIMES_PRODUCES ## Variable:L"BootNext"
gEfiGlobalVariableGuid
gEdkiiCapsuleOnDiskNameGuid ## SOMETIMES_CONSUMES ## GUID
[Depex]
gEfiVariableWriteArchProtocolGuid

View File

@ -9,7 +9,7 @@
ProcessCapsules(), ProcessTheseCapsules() will receive untrusted
input and do basic validation.
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -92,10 +92,41 @@ IsValidCapsuleHeader (
IN UINT64 CapsuleSize
);
/**
Return if this capsule is a capsule name capsule, based upon CapsuleHeader.
@param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER
@retval TRUE It is a capsule name capsule.
@retval FALSE It is not a capsule name capsule.
**/
BOOLEAN
IsCapsuleNameCapsule (
IN EFI_CAPSULE_HEADER *CapsuleHeader
);
/**
Check the integrity of the capsule name capsule.
If the capsule is vaild, return the physical address of each capsule name string.
@param[in] CapsuleHeader Pointer to the capsule header of a capsule name capsule.
@param[out] CapsuleNameNum Number of capsule name.
@retval NULL Capsule name capsule is not valid.
@retval CapsuleNameBuf Array of capsule name physical address.
**/
EFI_PHYSICAL_ADDRESS *
ValidateCapsuleNameCapsuleIntegrity (
IN EFI_CAPSULE_HEADER *CapsuleHeader,
OUT UINTN *CapsuleNameNum
);
extern BOOLEAN mDxeCapsuleLibEndOfDxe;
BOOLEAN mNeedReset = FALSE;
VOID **mCapsulePtr;
CHAR16 **mCapsuleNamePtr;
EFI_STATUS *mCapsuleStatusArray;
UINT32 mCapsuleTotalNumber;
@ -116,6 +147,7 @@ EFI_STATUS
EFIAPI
ProcessThisCapsuleImage (
IN EFI_CAPSULE_HEADER *CapsuleHeader,
IN CHAR16 *CapFileName, OPTIONAL
OUT BOOLEAN *ResetRequired OPTIONAL
);
@ -185,6 +217,18 @@ InitCapsulePtr (
{
EFI_PEI_HOB_POINTERS HobPointer;
UINTN Index;
UINTN Index2;
UINTN Index3;
UINTN CapsuleNameNumber;
UINTN CapsuleNameTotalNumber;
UINTN CapsuleNameCapsuleTotalNumber;
VOID **CapsuleNameCapsulePtr;
EFI_PHYSICAL_ADDRESS *CapsuleNameAddress;
CapsuleNameNumber = 0;
CapsuleNameTotalNumber = 0;
CapsuleNameCapsuleTotalNumber = 0;
CapsuleNameCapsulePtr = NULL;
//
// Find all capsule images from hob
@ -194,7 +238,11 @@ InitCapsulePtr (
if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) {
HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid
} else {
mCapsuleTotalNumber++;
if (IsCapsuleNameCapsule((VOID *)(UINTN)HobPointer.Capsule->BaseAddress)) {
CapsuleNameCapsuleTotalNumber++;
} else {
mCapsuleTotalNumber++;
}
}
HobPointer.Raw = GET_NEXT_HOB (HobPointer);
}
@ -224,15 +272,68 @@ InitCapsulePtr (
}
SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * mCapsuleTotalNumber, EFI_NOT_READY);
CapsuleNameCapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleNameCapsuleTotalNumber);
if (CapsuleNameCapsulePtr == NULL) {
DEBUG ((DEBUG_ERROR, "Allocate CapsuleNameCapsulePtr fail!\n"));
FreePool (mCapsulePtr);
FreePool (mCapsuleStatusArray);
mCapsulePtr = NULL;
mCapsuleStatusArray = NULL;
mCapsuleTotalNumber = 0;
return ;
}
//
// Find all capsule images from hob
//
HobPointer.Raw = GetHobList ();
Index = 0;
Index = 0;
Index2 = 0;
while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {
mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
if (IsCapsuleNameCapsule ((VOID *) (UINTN) HobPointer.Capsule->BaseAddress)) {
CapsuleNameCapsulePtr [Index2++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
} else {
mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;
}
HobPointer.Raw = GET_NEXT_HOB (HobPointer);
}
//
// Find Capsule On Disk Names
//
for (Index = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {
CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
if (CapsuleNameAddress != NULL ) {
CapsuleNameTotalNumber += CapsuleNameNumber;
}
}
if (CapsuleNameTotalNumber == mCapsuleTotalNumber) {
mCapsuleNamePtr = (CHAR16 **) AllocateZeroPool (sizeof (CHAR16 *) * mCapsuleTotalNumber);
if (mCapsuleNamePtr == NULL) {
DEBUG ((DEBUG_ERROR, "Allocate mCapsuleNamePtr fail!\n"));
FreePool (mCapsulePtr);
FreePool (mCapsuleStatusArray);
FreePool (CapsuleNameCapsulePtr);
mCapsulePtr = NULL;
mCapsuleStatusArray = NULL;
mCapsuleTotalNumber = 0;
return ;
}
for (Index = 0, Index3 = 0; Index < CapsuleNameCapsuleTotalNumber; Index ++) {
CapsuleNameAddress = ValidateCapsuleNameCapsuleIntegrity (CapsuleNameCapsulePtr[Index], &CapsuleNameNumber);
if (CapsuleNameAddress != NULL ) {
for (Index2 = 0; Index2 < CapsuleNameNumber; Index2 ++) {
mCapsuleNamePtr[Index3 ++] = (CHAR16 *)(UINTN) CapsuleNameAddress[Index2];
}
}
}
} else {
mCapsuleNamePtr = NULL;
}
FreePool (CapsuleNameCapsulePtr);
}
/**
@ -396,6 +497,7 @@ ProcessTheseCapsules (
ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;
UINT16 EmbeddedDriverCount;
BOOLEAN ResetRequired;
CHAR16 *CapsuleName;
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));
@ -408,6 +510,7 @@ ProcessTheseCapsules (
// 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"));
mNeedReset = TRUE;
return EFI_SUCCESS;
}
@ -430,10 +533,11 @@ ProcessTheseCapsules (
//
for (Index = 0; Index < mCapsuleTotalNumber; Index++) {
CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
CapsuleName = (mCapsuleNamePtr == NULL) ? NULL : mCapsuleNamePtr[Index];
if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));
DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));
Status = ProcessThisCapsuleImage (CapsuleHeader, NULL);
Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, NULL);
mCapsuleStatusArray [Index] = EFI_SUCCESS;
DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n", Status));
break;
@ -451,6 +555,7 @@ ProcessTheseCapsules (
continue;
}
CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];
CapsuleName = (mCapsuleNamePtr == NULL) ? NULL : mCapsuleNamePtr[Index];
if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {
//
// Call capsule library to process capsule image.
@ -471,7 +576,7 @@ ProcessTheseCapsules (
if ((!FirstRound) || (EmbeddedDriverCount == 0)) {
DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n", CapsuleHeader));
ResetRequired = FALSE;
Status = ProcessThisCapsuleImage (CapsuleHeader, &ResetRequired);
Status = ProcessThisCapsuleImage (CapsuleHeader, CapsuleName, &ResetRequired);
mCapsuleStatusArray [Index] = Status;
DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status));
@ -530,7 +635,8 @@ DoResetSystem (
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.
If there is no EFI_HOB_UEFI_CAPSULE, it means error occurs, force reset to
normal boot path.
This routine should be called twice in BDS.
1) The first call must be before EndOfDxe. The system capsules is processed.

View File

@ -1,7 +1,7 @@
/** @file
DXE capsule report related function.
Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -29,6 +29,18 @@
#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.
@ -174,6 +186,7 @@ RecordCapsuleStatusVariable (
@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.
@ -184,7 +197,8 @@ RecordFmpCapsuleStatusVariable (
IN EFI_STATUS CapsuleStatus,
IN UINTN PayloadIndex,
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL
IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OPTIONAL
IN CHAR16 *CapFileName OPTIONAL
)
{
EFI_CAPSULE_RESULT_VARIABLE_HEADER *CapsuleResultVariableHeader;
@ -194,8 +208,11 @@ RecordFmpCapsuleStatusVariable (
UINTN CapsuleResultVariableSize;
CHAR16 *DevicePathStr;
UINTN DevicePathStrSize;
UINTN CapFileNameSize;
DevicePathStr = NULL;
CapFileNameSize = sizeof(CHAR16);
DevicePathStr = NULL;
if (FmpDevicePath != NULL) {
DevicePathStr = ConvertDevicePathToText (FmpDevicePath, FALSE, FALSE);
}
@ -204,10 +221,16 @@ RecordFmpCapsuleStatusVariable (
} else {
DevicePathStrSize = sizeof(CHAR16);
}
if (CapFileName != NULL) {
CapFileNameSize = StrSize(CapFileName);
}
//
// Allocate zero CHAR16 for CapsuleFileName.
// Allocate room for CapsuleFileName.
//
CapsuleResultVariableSize = sizeof(EFI_CAPSULE_RESULT_VARIABLE_HEADER) + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + sizeof(CHAR16) + DevicePathStrSize;
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;
@ -225,8 +248,13 @@ RecordFmpCapsuleStatusVariable (
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) + sizeof(CHAR16), DevicePathStr, DevicePathStrSize);
CopyMem ((UINT8 *)CapsuleResultVariableFmp + sizeof(EFI_CAPSULE_RESULT_VARIABLE_FMP) + CapFileNameSize, DevicePathStr, DevicePathStrSize);
FreePool (DevicePathStr);
DevicePathStr = NULL;
}
@ -400,6 +428,31 @@ InitCapsuleUpdateVariable (
}
}
/**
Initialize capsule relocation info variable.
**/
VOID
InitCapsuleRelocationInfo (
VOID
)
{
EFI_STATUS Status;
EDKII_VARIABLE_LOCK_PROTOCOL *VariableLock;
CoDClearCapsuleRelocationInfo();
//
// Unlock Capsule On Disk relocation Info variable only when Capsule On Disk flag is enabled
//
if (!CoDCheckCapsuleOnDiskFlag()) {
Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);
if (!EFI_ERROR (Status)) {
Status = VariableLock->RequestToLock (VariableLock, COD_RELOCATION_INFO_VAR_NAME, &gEfiCapsuleVendorGuid);
ASSERT_EFI_ERROR (Status);
}
}
}
/**
Initialize capsule related variables.
**/
@ -411,6 +464,8 @@ InitCapsuleVariable (
InitCapsuleUpdateVariable();
InitCapsuleMaxVariable();
InitCapsuleLastVariable();
InitCapsuleRelocationInfo();
//
// No need to clear L"Capsule####", because OS/APP should refer L"CapsuleLast"
// to check status and delete them.

View File

@ -3,7 +3,7 @@
Dummy function for runtime module, because CapsuleDxeRuntime
does not need record capsule status variable.
Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -39,6 +39,7 @@ RecordCapsuleStatusVariable (
@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.
@ -49,7 +50,8 @@ RecordFmpCapsuleStatusVariable (
IN EFI_STATUS CapsuleStatus,
IN UINTN PayloadIndex,
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,
IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL
IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OPTIONAL
IN CHAR16 *CapFileName OPTIONAL
)
{
return EFI_UNSUPPORTED;

View File

@ -3,7 +3,7 @@
#
# Capsule library instance for DXE_RUNTIME_DRIVER module types.
#
# Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2016 - 2019, Intel Corporation. All rights reserved.<BR>
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
##
@ -68,6 +68,7 @@
gEfiEndOfDxeEventGroupGuid ## CONSUMES ## Event
gEfiEventReadyToBootGuid ## CONSUMES ## Event
gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event
gEdkiiCapsuleOnDiskNameGuid ## SOMETIMES_CONSUMES ## GUID
[Depex]
gEfiVariableWriteArchProtocolGuid

View File

@ -1,7 +1,7 @@
/** @file
Null Dxe Capsule Library instance does nothing and returns unsupport status.
Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2007 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -85,3 +85,86 @@ ProcessCapsules (
return EFI_UNSUPPORTED;
}
/**
This routine is called to check if CapsuleOnDisk flag in OsIndications Variable
is enabled.
@retval TRUE Flag is enabled
@retval FALSE Flag is not enabled
**/
BOOLEAN
EFIAPI
CoDCheckCapsuleOnDiskFlag(
VOID
)
{
return FALSE;
}
/**
This routine is called to clear CapsuleOnDisk flags including OsIndications and BootNext variable.
@retval EFI_SUCCESS All Capsule On Disk flags are cleared
**/
EFI_STATUS
EFIAPI
CoDClearCapsuleOnDiskFlag(
VOID
)
{
return EFI_UNSUPPORTED;
}
/**
Relocate Capsule on Disk from EFI system partition.
Two solution to deliver Capsule On Disk:
Solution A: If PcdCapsuleInRamSupport is enabled, relocate Capsule On Disk to memory and call UpdateCapsule().
Solution B: If PcdCapsuleInRamSupport is disabled, relocate Capsule On Disk to a platform-specific NV storage
device with BlockIo protocol.
Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
Function will stall 100ms between each retry.
Side Effects:
Capsule Delivery Supported Flag in OsIndication variable and BootNext variable will be cleared.
Solution B: Content corruption. Block IO write directly touches low level write. Orignal partitions, file
systems of the relocation device will be corrupted.
@param[in] MaxRetry Max Connection Retry. Stall 100ms between each connection try to ensure
devices like USB can get enumerated. Input 0 means no retry.
@retval EFI_SUCCESS Capsule on Disk images are successfully relocated.
**/
EFI_STATUS
EFIAPI
CoDRelocateCapsule(
UINTN MaxRetry
)
{
return EFI_UNSUPPORTED;
}
/**
Remove the temp file from the root of EFI System Partition.
Device enumeration like USB costs time, user can input MaxRetry to tell function to retry.
Function will stall 100ms between each retry.
@param[in] MaxRetry Max Connection Retry. Stall 100ms between each connection try to ensure
devices like USB can get enumerated. Input 0 means no retry.
@retval EFI_SUCCESS Remove the temp file successfully.
**/
EFI_STATUS
EFIAPI
CoDRemoveTempFile (
UINTN MaxRetry
)
{
return EFI_UNSUPPORTED;
}