mirror of
https://github.com/Dasharo/edk2.git
synced 2026-06-13 10:16:24 -07:00
MdeModulePkg/DxeCapsuleLibFmp: Use CapsuleTransformation protocol
Optionally transforming a capsule via the protocol permits tweaking capsule format and/or adding additional layers of verification without embedding any specific details into DxeCapsuleLibFmp. The protocol must be part of the running firmware so drivers embedded into capsules can't affect processing of other capsules in this way. A failure to transform a capsule results in it being skipped. A successful transformation leads to its re-validation before further processing. Signed-off-by: Gustavo dos Santos Cardoso <gustavo_16a@hotmail.com> Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com>
This commit is contained in:
committed by
Sergii Dmytruk
parent
8e63b9a959
commit
32840a9cad
@@ -90,6 +90,7 @@
|
||||
gEfiBlockIoProtocolGuid ## CONSUMES
|
||||
gEfiDiskIoProtocolGuid ## CONSUMES
|
||||
gEdkiiVariablePolicyProtocolGuid ## CONSUMES
|
||||
gCapsuleTransformationProtocolGuid ## SOMETIMES_CONSUMES
|
||||
|
||||
[Guids]
|
||||
gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
**/
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Protocol/CapsuleTransformation.h>
|
||||
#include <Protocol/EsrtManagement.h>
|
||||
#include <Protocol/FirmwareManagementProgress.h>
|
||||
|
||||
@@ -37,6 +38,21 @@
|
||||
|
||||
extern EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *mFmpProgress;
|
||||
|
||||
/**
|
||||
Record capsule status variable.
|
||||
|
||||
@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 if this FMP is a system FMP or a device FMP, based upon CapsuleHeader.
|
||||
|
||||
@@ -132,6 +148,8 @@ CHAR16 **mCapsuleNamePtr;
|
||||
EFI_STATUS *mCapsuleStatusArray;
|
||||
UINT32 mCapsuleTotalNumber;
|
||||
|
||||
STATIC CAPSULE_TRANSFORMATION_PROTOCOL *CapsuleTransformation;
|
||||
|
||||
/**
|
||||
The firmware implements to process the capsule image.
|
||||
|
||||
@@ -643,18 +661,55 @@ ProcessTheseCapsules (
|
||||
// Call capsule library to process capsule image.
|
||||
//
|
||||
EmbeddedDriverCount = 0;
|
||||
if (IsFmpCapsule (CapsuleHeader)) {
|
||||
if (!IsFmpCapsule (CapsuleHeader)) {
|
||||
ReportCapsuleOutcome (ReportAddCapsule (Report, Index, CapsuleHeader), CAPSULE_NONFMP, EFI_ABORTED);
|
||||
mCapsuleStatusArray[Index] = EFI_ABORTED;
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = ValidateFmpCapsule (CapsuleHeader, &EmbeddedDriverCount);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "ValidateFmpCapsule failed with %r. Ignore!\n", Status));
|
||||
ReportCapsuleOutcome (ReportAddCapsule (Report, Index, CapsuleHeader), CAPSULE_REFUSED, Status);
|
||||
mCapsuleStatusArray[Index] = EFI_ABORTED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (CapsuleTransformation != NULL) {
|
||||
Status = CapsuleTransformation->Transform (CapsuleTransformation, &CapsuleHeader);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Capsule transformation failed with %r. Ignore!\n", Status));
|
||||
if ((Status == EFI_INVALID_PARAMETER) || (Status == EFI_UNSUPPORTED) || (Status == EFI_SECURITY_VIOLATION)) {
|
||||
//
|
||||
// Report issues with the capsule to the user.
|
||||
//
|
||||
RecordCapsuleStatusVariable (CapsuleHeader, Status);
|
||||
ReportCapsuleOutcome (ReportAddCapsule (Report, Index, CapsuleHeader), CAPSULE_REFUSED, Status);
|
||||
}
|
||||
|
||||
mCapsuleStatusArray[Index] = EFI_ABORTED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!IsFmpCapsule (CapsuleHeader)) {
|
||||
ReportCapsuleOutcome (ReportAddCapsule (Report, Index, CapsuleHeader), CAPSULE_NONFMP, EFI_ABORTED);
|
||||
mCapsuleStatusArray[Index] = EFI_ABORTED;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Re-validate the capsule after the transformation and obtain updated
|
||||
// driver count.
|
||||
//
|
||||
Status = ValidateFmpCapsule (CapsuleHeader, &EmbeddedDriverCount);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "ValidateFmpCapsule failed. Ignore!\n"));
|
||||
DEBUG ((DEBUG_ERROR, "ValidateFmpCapsule failed for transformed capsule with %r. Ignore!\n", Status));
|
||||
ReportCapsuleOutcome (ReportAddCapsule (Report, Index, CapsuleHeader), CAPSULE_REFUSED, Status);
|
||||
mCapsuleStatusArray[Index] = EFI_ABORTED;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
ReportCapsuleOutcome (ReportAddCapsule (Report, Index, CapsuleHeader), CAPSULE_NONFMP, EFI_ABORTED);
|
||||
mCapsuleStatusArray[Index] = EFI_ABORTED;
|
||||
continue;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "New EmbeddedDriverCount: %d\n", EmbeddedDriverCount));
|
||||
}
|
||||
|
||||
if ((!FirstRound) || (EmbeddedDriverCount == 0)) {
|
||||
@@ -775,6 +830,19 @@ ProcessCapsules (
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (!mDxeCapsuleLibEndOfDxe) {
|
||||
//
|
||||
// The lookup for this protocol must happen on the first call to not pick up
|
||||
// an implementation provided by an embedded driver of some capsule.
|
||||
//
|
||||
Status = gBS->LocateProtocol (
|
||||
&gCapsuleTransformationProtocolGuid,
|
||||
NULL,
|
||||
(VOID **)&CapsuleTransformation
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_INFO, "Discovered CapsuleTransformation protocol\n"));
|
||||
}
|
||||
|
||||
Status = ProcessTheseCapsules (TRUE, &CapsuleReport);
|
||||
|
||||
//
|
||||
|
||||
@@ -65,6 +65,7 @@
|
||||
gEfiFirmwareManagementProtocolGuid ## CONSUMES
|
||||
gEdkiiVariableLockProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gEdkiiFirmwareManagementProgressProtocolGuid ## SOMETIMES_CONSUMES
|
||||
gCapsuleTransformationProtocolGuid ## SOMETIMES_CONSUMES
|
||||
|
||||
[Guids]
|
||||
gEfiFmpCapsuleGuid ## SOMETIMES_CONSUMES ## GUID
|
||||
|
||||
Reference in New Issue
Block a user