mirror of https://github.com/acidanthera/audk.git
FmpDevicePkg/FmpDxe: Use new Fmp dependency libraries
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696 Remove the orginal Fmp Capsule Dependency implement, and use new FmpDependencyLib, FmpDependencyCheckLib and FmpDependencyDeviceLib APIs instead. A platform can perform the dependency check in a platform specific manner by implementing its own FmpDependencyCheckLib. Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Liming Gao <liming.gao@intel.com> Cc: Sean Brogan <sean.brogan@microsoft.com> Signed-off-by: Wei6 Xu <wei6.xu@intel.com> Reviewed-by: Sean Brogan <sean.brogan@microsoft.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
This commit is contained in:
parent
ba86bb2c4d
commit
0f30087b9a
|
@ -1,679 +0,0 @@
|
|||
/** @file
|
||||
Supports Capsule Dependency Expression.
|
||||
|
||||
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#include "FmpDxe.h"
|
||||
#include "Dependency.h"
|
||||
|
||||
//
|
||||
// Define the initial size of the dependency expression evaluation stack
|
||||
//
|
||||
#define DEPEX_STACK_SIZE_INCREMENT 0x1000
|
||||
|
||||
//
|
||||
// Type of stack element
|
||||
//
|
||||
typedef enum {
|
||||
BooleanType,
|
||||
VersionType
|
||||
} ELEMENT_TYPE;
|
||||
|
||||
//
|
||||
// Value of stack element
|
||||
//
|
||||
typedef union {
|
||||
BOOLEAN Boolean;
|
||||
UINT32 Version;
|
||||
} ELEMENT_VALUE;
|
||||
|
||||
//
|
||||
// Stack element used to evaluate dependency expressions
|
||||
//
|
||||
typedef struct {
|
||||
ELEMENT_VALUE Value;
|
||||
ELEMENT_TYPE Type;
|
||||
} DEPEX_ELEMENT;
|
||||
|
||||
//
|
||||
// Global variable used to support dependency evaluation
|
||||
//
|
||||
UINTN mNumberOfFmpInstance = 0;
|
||||
EFI_FIRMWARE_IMAGE_DESCRIPTOR **mFmpImageInfoBuf = NULL;
|
||||
|
||||
//
|
||||
// Indicates the status of dependency check, default value is DEPENDENCIES_SATISFIED.
|
||||
//
|
||||
UINT8 mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;
|
||||
|
||||
//
|
||||
// Global stack used to evaluate dependency expressions
|
||||
//
|
||||
DEPEX_ELEMENT *mDepexEvaluationStack = NULL;
|
||||
DEPEX_ELEMENT *mDepexEvaluationStackEnd = NULL;
|
||||
DEPEX_ELEMENT *mDepexEvaluationStackPointer = NULL;
|
||||
|
||||
/**
|
||||
Grow size of the Depex stack
|
||||
|
||||
@retval EFI_SUCCESS Stack successfully growed.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GrowDepexStack (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DEPEX_ELEMENT *NewStack;
|
||||
UINTN Size;
|
||||
|
||||
Size = DEPEX_STACK_SIZE_INCREMENT;
|
||||
if (mDepexEvaluationStack != NULL) {
|
||||
Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack);
|
||||
}
|
||||
|
||||
NewStack = AllocatePool (Size * sizeof (DEPEX_ELEMENT));
|
||||
if (NewStack == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
if (mDepexEvaluationStack != NULL) {
|
||||
//
|
||||
// Copy to Old Stack to the New Stack
|
||||
//
|
||||
CopyMem (
|
||||
NewStack,
|
||||
mDepexEvaluationStack,
|
||||
(mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (DEPEX_ELEMENT)
|
||||
);
|
||||
|
||||
//
|
||||
// Free The Old Stack
|
||||
//
|
||||
FreePool (mDepexEvaluationStack);
|
||||
}
|
||||
|
||||
//
|
||||
// Make the Stack pointer point to the old data in the new stack
|
||||
//
|
||||
mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack);
|
||||
mDepexEvaluationStack = NewStack;
|
||||
mDepexEvaluationStackEnd = NewStack + Size;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Push an element onto the Stack.
|
||||
|
||||
@param[in] Value Value to push.
|
||||
@param[in] Type Element Type
|
||||
|
||||
@retval EFI_SUCCESS The value was pushed onto the stack.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough system memory to grow the stack.
|
||||
@retval EFI_INVALID_PARAMETER Wrong stack element type.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Push (
|
||||
IN UINT32 Value,
|
||||
IN UINTN Type
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
DEPEX_ELEMENT Element;
|
||||
|
||||
//
|
||||
// Check Type
|
||||
//
|
||||
if (Type != BooleanType && Type != VersionType) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Check for a stack overflow condition
|
||||
//
|
||||
if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) {
|
||||
//
|
||||
// Grow the stack
|
||||
//
|
||||
Status = GrowDepexStack ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Element.Value.Version = Value;
|
||||
Element.Type = Type;
|
||||
|
||||
//
|
||||
// Push the item onto the stack
|
||||
//
|
||||
*mDepexEvaluationStackPointer = Element;
|
||||
mDepexEvaluationStackPointer++;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Pop an element from the stack.
|
||||
|
||||
@param[out] Element Element to pop.
|
||||
@param[in] Type Type of element.
|
||||
|
||||
@retval EFI_SUCCESS The value was popped onto the stack.
|
||||
@retval EFI_ACCESS_DENIED The pop operation underflowed the stack.
|
||||
@retval EFI_INVALID_PARAMETER Type is mismatched.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
Pop (
|
||||
OUT DEPEX_ELEMENT *Element,
|
||||
IN ELEMENT_TYPE Type
|
||||
)
|
||||
{
|
||||
//
|
||||
// Check for a stack underflow condition
|
||||
//
|
||||
if (mDepexEvaluationStackPointer == mDepexEvaluationStack) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// Pop the item off the stack
|
||||
//
|
||||
mDepexEvaluationStackPointer--;
|
||||
*Element = *mDepexEvaluationStackPointer;
|
||||
if ((*Element).Type != Type) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Evaluate the dependencies.
|
||||
|
||||
@param[in] Dependencies Dependency expressions.
|
||||
@param[in] DependenciesSize Size of Dependency expressions.
|
||||
|
||||
@retval TRUE Dependency expressions evaluate to TRUE.
|
||||
@retval FALSE Dependency expressions evaluate to FALSE.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EvaluateDependencies (
|
||||
IN CONST EFI_FIRMWARE_IMAGE_DEP * Dependencies,
|
||||
IN CONST UINTN DependenciesSize
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *Iterator;
|
||||
UINT8 Index;
|
||||
DEPEX_ELEMENT Element1;
|
||||
DEPEX_ELEMENT Element2;
|
||||
GUID ImageTypeId;
|
||||
UINT32 Version;
|
||||
|
||||
if (Dependencies == NULL || DependenciesSize == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Clean out memory leaks in Depex Boolean stack. Leaks are only caused by
|
||||
// incorrectly formed DEPEX expressions
|
||||
//
|
||||
mDepexEvaluationStackPointer = mDepexEvaluationStack;
|
||||
|
||||
Iterator = (UINT8 *) Dependencies->Dependencies;
|
||||
while (Iterator < (UINT8 *) Dependencies->Dependencies + DependenciesSize) {
|
||||
switch (*Iterator)
|
||||
{
|
||||
case EFI_FMP_DEP_PUSH_GUID:
|
||||
if (Iterator + sizeof (EFI_GUID) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
CopyGuid (&ImageTypeId, (EFI_GUID *) (Iterator + 1));
|
||||
Iterator = Iterator + sizeof (EFI_GUID);
|
||||
|
||||
for (Index = 0; Index < mNumberOfFmpInstance; Index ++){
|
||||
if (mFmpImageInfoBuf[Index] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if(CompareGuid (&mFmpImageInfoBuf[Index]->ImageTypeId, &ImageTypeId)){
|
||||
Status = Push (mFmpImageInfoBuf[Index]->Version, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Index == mNumberOfFmpInstance) {
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_PUSH_VERSION:
|
||||
if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Version = *(UINT32 *) (Iterator + 1);
|
||||
Status = Push (Version, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Iterator = Iterator + sizeof (UINT32);
|
||||
break;
|
||||
case EFI_FMP_DEP_VERSION_STR:
|
||||
Iterator += AsciiStrnLenS ((CHAR8 *) Iterator, DependenciesSize - (Iterator - Dependencies->Dependencies));
|
||||
break;
|
||||
case EFI_FMP_DEP_AND:
|
||||
Status = Pop (&Element1, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Pop (&Element2, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Push (Element1.Value.Boolean & Element2.Value.Boolean, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_OR:
|
||||
Status = Pop (&Element1, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Pop(&Element2, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Push (Element1.Value.Boolean | Element2.Value.Boolean, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_NOT:
|
||||
Status = Pop (&Element1, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Push (!(Element1.Value.Boolean), BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_TRUE:
|
||||
Status = Push (TRUE, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_FALSE:
|
||||
Status = Push (FALSE, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_EQ:
|
||||
Status = Pop (&Element1, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Pop (&Element2, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = (Element1.Value.Version == Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_GT:
|
||||
Status = Pop (&Element1, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Pop (&Element2, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = (Element1.Value.Version > Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_GTE:
|
||||
Status = Pop (&Element1, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Pop (&Element2, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = (Element1.Value.Version >= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_LT:
|
||||
Status = Pop (&Element1, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Pop (&Element2, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = (Element1.Value.Version < Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_LTE:
|
||||
Status = Pop (&Element1, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = Pop (&Element2, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
Status = (Element1.Value.Version <= Element2.Value.Version) ? Push (TRUE, BooleanType) : Push (FALSE, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_END:
|
||||
Status = Pop (&Element1, BooleanType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
return Element1.Value.Boolean;
|
||||
default:
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Error;
|
||||
}
|
||||
Iterator++;
|
||||
}
|
||||
|
||||
Error:
|
||||
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): EvaluateDependencies() - RESULT = FALSE (Status = %r)\n", mImageIdName, Status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Validate the dependency expression and output its size.
|
||||
|
||||
@param[in] ImageDepex Pointer to the EFI_FIRMWARE_IMAGE_DEP.
|
||||
@param[in] MaxDepexSize Max size of the dependency.
|
||||
@param[out] DepexSize Size of dependency.
|
||||
|
||||
@retval TRUE The capsule is valid.
|
||||
@retval FALSE The capsule is invalid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
ValidateImageDepex (
|
||||
IN EFI_FIRMWARE_IMAGE_DEP *ImageDepex,
|
||||
IN CONST UINTN MaxDepexSize,
|
||||
OUT UINT32 *DepexSize
|
||||
)
|
||||
{
|
||||
UINT8 *Depex;
|
||||
|
||||
*DepexSize = 0;
|
||||
Depex = ImageDepex->Dependencies;
|
||||
while (Depex < ImageDepex->Dependencies + MaxDepexSize) {
|
||||
switch (*Depex)
|
||||
{
|
||||
case EFI_FMP_DEP_PUSH_GUID:
|
||||
Depex += sizeof (EFI_GUID) + 1;
|
||||
break;
|
||||
case EFI_FMP_DEP_PUSH_VERSION:
|
||||
Depex += sizeof (UINT32) + 1;
|
||||
break;
|
||||
case EFI_FMP_DEP_VERSION_STR:
|
||||
Depex += AsciiStrnLenS ((CHAR8 *) Depex, ImageDepex->Dependencies + MaxDepexSize - Depex) + 1;
|
||||
break;
|
||||
case EFI_FMP_DEP_AND:
|
||||
case EFI_FMP_DEP_OR:
|
||||
case EFI_FMP_DEP_NOT:
|
||||
case EFI_FMP_DEP_TRUE:
|
||||
case EFI_FMP_DEP_FALSE:
|
||||
case EFI_FMP_DEP_EQ:
|
||||
case EFI_FMP_DEP_GT:
|
||||
case EFI_FMP_DEP_GTE:
|
||||
case EFI_FMP_DEP_LT:
|
||||
case EFI_FMP_DEP_LTE:
|
||||
Depex += 1;
|
||||
break;
|
||||
case EFI_FMP_DEP_END:
|
||||
Depex += 1;
|
||||
*DepexSize = (UINT32)(Depex - ImageDepex->Dependencies);
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the size of dependencies. Assume the dependencies is validated before
|
||||
calling this function.
|
||||
|
||||
@param[in] Dependencies Pointer to the EFI_FIRMWARE_IMAGE_DEP.
|
||||
|
||||
@retval The size of dependencies.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
GetDepexSize (
|
||||
IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
if (Dependencies == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Index = 0;
|
||||
while (Dependencies->Dependencies[Index] != EFI_FMP_DEP_END) {
|
||||
Index ++;
|
||||
}
|
||||
|
||||
return Index + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Check dependency for firmware update.
|
||||
|
||||
@param[in] ImageTypeId Image Type Id.
|
||||
@param[in] Version New version.
|
||||
@param[in] Dependencies The dependencies.
|
||||
@param[in] DependenciesSize Size of the dependencies
|
||||
@param[out] IsSatisfied Indicate the dependencies is satisfied or not.
|
||||
|
||||
@retval EFI_SUCCESS Dependency Evaluation is successful.
|
||||
@retval Others Dependency Evaluation fails with unexpected error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EvaluateImageDependencies (
|
||||
IN CONST EFI_GUID ImageTypeId,
|
||||
IN CONST UINT32 Version,
|
||||
IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies,
|
||||
IN CONST UINT32 DependenciesSize,
|
||||
OUT BOOLEAN *IsSatisfied
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_HANDLE *HandleBuffer;
|
||||
UINTN Index;
|
||||
EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
|
||||
UINTN ImageInfoSize;
|
||||
UINT32 FmpImageInfoDescriptorVer;
|
||||
UINT8 FmpImageInfoCount;
|
||||
UINTN DescriptorSize;
|
||||
UINT32 PackageVersion;
|
||||
CHAR16 *PackageVersionName;
|
||||
UINTN DepexSize;
|
||||
|
||||
*IsSatisfied = TRUE;
|
||||
PackageVersionName = NULL;
|
||||
|
||||
//
|
||||
// Get ImageDescriptors of all FMP instances, and archive them for depex evaluation.
|
||||
//
|
||||
Status = gBS->LocateHandleBuffer (
|
||||
ByProtocol,
|
||||
&gEfiFirmwareManagementProtocolGuid,
|
||||
NULL,
|
||||
&mNumberOfFmpInstance,
|
||||
&HandleBuffer
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
mFmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * mNumberOfFmpInstance);
|
||||
if (mFmpImageInfoBuf == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
|
||||
Status = gBS->HandleProtocol (
|
||||
HandleBuffer[Index],
|
||||
&gEfiFirmwareManagementProtocolGuid,
|
||||
(VOID **) &Fmp
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ImageInfoSize = 0;
|
||||
Status = Fmp->GetImageInfo (
|
||||
Fmp,
|
||||
&ImageInfoSize,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
);
|
||||
if (Status != EFI_BUFFER_TOO_SMALL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mFmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);
|
||||
if (mFmpImageInfoBuf[Index] == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = Fmp->GetImageInfo (
|
||||
Fmp,
|
||||
&ImageInfoSize, // ImageInfoSize
|
||||
mFmpImageInfoBuf[Index], // ImageInfo
|
||||
&FmpImageInfoDescriptorVer, // DescriptorVersion
|
||||
&FmpImageInfoCount, // DescriptorCount
|
||||
&DescriptorSize, // DescriptorSize
|
||||
&PackageVersion, // PackageVersion
|
||||
&PackageVersionName // PackageVersionName
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
FreePool (mFmpImageInfoBuf[Index]);
|
||||
mFmpImageInfoBuf[Index] = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (PackageVersionName != NULL) {
|
||||
FreePool (PackageVersionName);
|
||||
PackageVersionName = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Step 1 - Evaluate firmware image's depex, against the version of other Fmp instances.
|
||||
//
|
||||
if (Dependencies != NULL) {
|
||||
*IsSatisfied = EvaluateDependencies (Dependencies, DependenciesSize);
|
||||
}
|
||||
|
||||
if (!*IsSatisfied) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Step 2 - Evaluate the depex of all other Fmp instances, against the new version in
|
||||
// the firmware image.
|
||||
//
|
||||
|
||||
//
|
||||
// Update the new version to mFmpImageInfoBuf.
|
||||
//
|
||||
for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
|
||||
if (mFmpImageInfoBuf[Index] != NULL) {
|
||||
if (CompareGuid (&ImageTypeId, &mFmpImageInfoBuf[Index]->ImageTypeId)) {
|
||||
mFmpImageInfoBuf[Index]->Version = Version;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Evaluate the Dependencies one by one.
|
||||
//
|
||||
for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
|
||||
if (mFmpImageInfoBuf[Index] != NULL) {
|
||||
//
|
||||
// Skip the Fmp instance to be "SetImage".
|
||||
//
|
||||
if (CompareGuid (&ImageTypeId, &mFmpImageInfoBuf[Index]->ImageTypeId)) {
|
||||
continue;
|
||||
}
|
||||
if ((mFmpImageInfoBuf[Index]->AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) &&
|
||||
mFmpImageInfoBuf[Index]->Dependencies != NULL) {
|
||||
//
|
||||
// Get the size of depex.
|
||||
// Assume that the dependencies in EFI_FIRMWARE_IMAGE_DESCRIPTOR is validated when PopulateDescriptor().
|
||||
//
|
||||
DepexSize = GetDepexSize (mFmpImageInfoBuf[Index]->Dependencies);
|
||||
if (DepexSize > 0) {
|
||||
*IsSatisfied = EvaluateDependencies (mFmpImageInfoBuf[Index]->Dependencies, DepexSize);
|
||||
if (!*IsSatisfied) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (mFmpImageInfoBuf != NULL) {
|
||||
for (Index = 0; Index < mNumberOfFmpInstance; Index ++) {
|
||||
if (mFmpImageInfoBuf[Index] != NULL) {
|
||||
FreePool (mFmpImageInfoBuf[Index]);
|
||||
}
|
||||
}
|
||||
FreePool (mFmpImageInfoBuf);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/** @file
|
||||
Fmp Capsule Dependency support functions for Firmware Management Protocol based
|
||||
firmware updates.
|
||||
|
||||
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#ifndef __DEPENDENCY_H__
|
||||
#define __DEPENDENCY_H__
|
||||
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Protocol/FirmwareManagement.h>
|
||||
|
||||
#define DEPENDENCIES_SATISFIED 0
|
||||
#define DEPENDENCIES_UNSATISFIED 1
|
||||
#define DEPENDENCIES_INVALID 2
|
||||
|
||||
extern UINT8 mDependenciesCheckStatus;
|
||||
|
||||
/**
|
||||
Validate the dependency expression and output its size.
|
||||
|
||||
@param[in] ImageDepex Pointer to the EFI_FIRMWARE_IMAGE_DEP.
|
||||
@param[in] MaxDepexSize Max size of the dependency.
|
||||
@param[out] DepexSize Size of dependency.
|
||||
|
||||
@retval TRUE The capsule is valid.
|
||||
@retval FALSE The capsule is invalid.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
ValidateImageDepex (
|
||||
IN EFI_FIRMWARE_IMAGE_DEP *ImageDepex,
|
||||
IN CONST UINTN MaxDepexSize,
|
||||
OUT UINT32 *DepexSize
|
||||
);
|
||||
|
||||
/**
|
||||
Check dependency for firmware update.
|
||||
|
||||
@param[in] ImageTypeId Image Type Id.
|
||||
@param[in] Version New version.
|
||||
@param[in] Dependencies The dependencies.
|
||||
@param[in] DepexSize Size of the dependencies
|
||||
@param[out] IsSatisfied Indicate the dependencies is satisfied or not.
|
||||
|
||||
@retval EFI_SUCCESS Dependency Evaluation is successful.
|
||||
@retval Others Dependency Evaluation fails with unexpected error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EvaluateImageDependencies (
|
||||
IN CONST EFI_GUID ImageTypeId,
|
||||
IN CONST UINT32 Version,
|
||||
IN CONST EFI_FIRMWARE_IMAGE_DEP *Dependencies,
|
||||
IN CONST UINT32 DepexSize,
|
||||
OUT BOOLEAN *IsSatisfied
|
||||
);
|
||||
|
||||
#endif
|
|
@ -12,7 +12,6 @@
|
|||
|
||||
#include "FmpDxe.h"
|
||||
#include "VariableSupport.h"
|
||||
#include "Dependency.h"
|
||||
|
||||
///
|
||||
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
|
||||
|
@ -81,7 +80,8 @@ const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate =
|
|||
NULL, // LsvVariableName
|
||||
NULL, // LastAttemptStatusVariableName
|
||||
NULL, // LastAttemptVersionVariableName
|
||||
NULL // FmpStateVariableName
|
||||
NULL, // FmpStateVariableName
|
||||
TRUE // DependenciesSatisfied
|
||||
};
|
||||
|
||||
///
|
||||
|
@ -276,13 +276,7 @@ PopulateDescriptor (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
VOID *Image;
|
||||
UINTN ImageSize;
|
||||
BOOLEAN IsDepexValid;
|
||||
UINT32 DepexSize;
|
||||
|
||||
Image = NULL;
|
||||
ImageSize = 0;
|
||||
UINT32 DependenciesSize;
|
||||
|
||||
if (Private->DescriptorPopulated) {
|
||||
return;
|
||||
|
@ -387,46 +381,18 @@ PopulateDescriptor (
|
|||
Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);
|
||||
|
||||
//
|
||||
// Get the dependency from the FmpDeviceLib and populate it to the descriptor.
|
||||
// Get the dependency from the FmpDependencyDeviceLib.
|
||||
//
|
||||
Private->Descriptor.Dependencies = NULL;
|
||||
|
||||
//
|
||||
// Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
|
||||
//
|
||||
if (Private->Descriptor.AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) {
|
||||
//
|
||||
// The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.
|
||||
// Get the dependency from the Image.
|
||||
//
|
||||
ImageSize = Private->Descriptor.Size;
|
||||
Image = AllocatePool (ImageSize);
|
||||
if (Image != NULL) {
|
||||
Status = FmpDeviceGetImage (Image, &ImageSize);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
FreePool (Image);
|
||||
Image = AllocatePool (ImageSize);
|
||||
if (Image != NULL) {
|
||||
Status = FmpDeviceGetImage (Image, &ImageSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!EFI_ERROR (Status) && Image != NULL) {
|
||||
IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) Image, ImageSize, &DepexSize);
|
||||
if (IsDepexValid) {
|
||||
Private->Descriptor.Dependencies = AllocatePool (DepexSize);
|
||||
if (Private->Descriptor.Dependencies != NULL) {
|
||||
CopyMem (Private->Descriptor.Dependencies->Dependencies, Image, DepexSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
|
||||
Private->Descriptor.Dependencies = GetFmpDependency (&DependenciesSize);
|
||||
}
|
||||
|
||||
Private->DescriptorPopulated = TRUE;
|
||||
|
||||
if (Image != NULL) {
|
||||
FreePool (Image);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -588,17 +554,12 @@ GetTheImage (
|
|||
EFI_STATUS Status;
|
||||
FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
|
||||
UINTN Size;
|
||||
UINT8 *ImageBuffer;
|
||||
UINTN ImageBufferSize;
|
||||
UINT32 DepexSize;
|
||||
|
||||
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
ImageBuffer = NULL;
|
||||
DepexSize = 0;
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
//
|
||||
// Retrieve the private context structure
|
||||
|
@ -628,45 +589,8 @@ GetTheImage (
|
|||
if (EFI_ERROR (Status)) {
|
||||
Size = 0;
|
||||
}
|
||||
|
||||
//
|
||||
// The parameter "Image" of FmpDeviceGetImage() is extended to contain the dependency.
|
||||
// Get the Fmp Payload from the Image.
|
||||
//
|
||||
ImageBufferSize = Size;
|
||||
ImageBuffer = AllocatePool (ImageBufferSize);
|
||||
if (ImageBuffer == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
FreePool (ImageBuffer);
|
||||
ImageBuffer = AllocatePool (ImageBufferSize);
|
||||
if (ImageBuffer == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - AllocatePool fails.\n", mImageIdName));
|
||||
Status = EFI_NOT_FOUND;
|
||||
goto cleanup;
|
||||
}
|
||||
Status = FmpDeviceGetImage (ImageBuffer, &ImageBufferSize);
|
||||
}
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
|
||||
//
|
||||
if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
|
||||
//
|
||||
// Validate the dependency to get its size.
|
||||
//
|
||||
ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP *) ImageBuffer, ImageBufferSize, &DepexSize);
|
||||
}
|
||||
|
||||
if (*ImageSize < ImageBufferSize - DepexSize) {
|
||||
*ImageSize = ImageBufferSize - DepexSize;
|
||||
if (*ImageSize < Size) {
|
||||
*ImageSize = Size;
|
||||
DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));
|
||||
Status = EFI_BUFFER_TOO_SMALL;
|
||||
goto cleanup;
|
||||
|
@ -678,17 +602,8 @@ GetTheImage (
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Image is after the dependency expression.
|
||||
//
|
||||
*ImageSize = ImageBufferSize - DepexSize;
|
||||
CopyMem (Image, ImageBuffer + DepexSize, *ImageSize);
|
||||
Status = EFI_SUCCESS;
|
||||
|
||||
Status = FmpDeviceGetImage (Image, ImageSize);
|
||||
cleanup:
|
||||
if (ImageBuffer != NULL) {
|
||||
FreePool (ImageBuffer);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -697,8 +612,9 @@ cleanup:
|
|||
Helper function to safely retrieve the FMP header from
|
||||
within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
|
||||
|
||||
@param[in] Image Pointer to the image.
|
||||
@param[in] ImageSize Size of the image.
|
||||
@param[in] Image Pointer to the image.
|
||||
@param[in] ImageSize Size of the image.
|
||||
@param[in] AdditionalHeaderSize Size of any headers that cannot be calculated by this function.
|
||||
@param[out] PayloadSize
|
||||
|
||||
@retval !NULL Valid pointer to the header.
|
||||
|
@ -709,22 +625,23 @@ VOID *
|
|||
GetFmpHeader (
|
||||
IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
|
||||
IN CONST UINTN ImageSize,
|
||||
IN CONST UINTN AdditionalHeaderSize,
|
||||
OUT UINTN *PayloadSize
|
||||
)
|
||||
{
|
||||
//
|
||||
// Check to make sure that operation can be safely performed.
|
||||
//
|
||||
if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) < (UINTN)Image || \
|
||||
((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) >= (UINTN)Image + ImageSize) {
|
||||
if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image || \
|
||||
((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize) {
|
||||
//
|
||||
// Pointer overflow. Invalid image.
|
||||
//
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
|
||||
return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
|
||||
*PayloadSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
|
||||
return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -811,8 +728,6 @@ CheckTheImage (
|
|||
UINT8 *PublicKeyDataXdrEnd;
|
||||
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
|
||||
UINT32 DependenciesSize;
|
||||
BOOLEAN IsDepexValid;
|
||||
BOOLEAN IsDepexSatisfied;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
RawSize = 0;
|
||||
|
@ -850,6 +765,11 @@ CheckTheImage (
|
|||
//
|
||||
*ImageUpdatable = IMAGE_UPDATABLE_VALID;
|
||||
|
||||
//
|
||||
// Set to satisfied and then if dependency evaluates to false it will update this flag.
|
||||
//
|
||||
Private->DependenciesSatisfied = TRUE;
|
||||
|
||||
if (Image == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
|
||||
//
|
||||
|
@ -935,11 +855,15 @@ CheckTheImage (
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the dependency from Image.
|
||||
//
|
||||
Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
|
||||
|
||||
//
|
||||
// Check the FmpPayloadHeader
|
||||
//
|
||||
FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );
|
||||
FmpPayloadHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );
|
||||
if (FmpPayloadHeader == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
|
||||
Status = EFI_ABORTED;
|
||||
|
@ -947,33 +871,10 @@ CheckTheImage (
|
|||
}
|
||||
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Check if there is dependency expression
|
||||
//
|
||||
IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader, FmpPayloadSize, &DependenciesSize);
|
||||
if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {
|
||||
//
|
||||
// Fmp payload is after dependency expression
|
||||
//
|
||||
Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader;
|
||||
FmpPayloadHeader = (UINT8 *) Dependencies + DependenciesSize;
|
||||
FmpPayloadSize = FmpPayloadSize - DependenciesSize;
|
||||
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
|
||||
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
||||
Status = EFI_SUCCESS;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is invalid.\n", mImageIdName));
|
||||
mDependenciesCheckStatus = DEPENDENCIES_INVALID;
|
||||
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
||||
Status = EFI_SUCCESS;
|
||||
goto cleanup;
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_WARN, "FmpDxe(%s): CheckTheImage() - No dependency associated in image.\n", mImageIdName));
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
|
||||
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
||||
Status = EFI_SUCCESS;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -993,14 +894,9 @@ CheckTheImage (
|
|||
//
|
||||
// Evaluate dependency expression
|
||||
//
|
||||
Status = EvaluateImageDependencies (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize, &IsDepexSatisfied);
|
||||
if (!IsDepexSatisfied || EFI_ERROR (Status)) {
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed %r.\n", mImageIdName, Status));
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency is not satisfied.\n", mImageIdName));
|
||||
}
|
||||
mDependenciesCheckStatus = DEPENDENCIES_UNSATISFIED;
|
||||
Private->DependenciesSatisfied = CheckFmpDependency (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize);
|
||||
if (!Private->DependenciesSatisfied) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));
|
||||
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
||||
Status = EFI_SUCCESS;
|
||||
goto cleanup;
|
||||
|
@ -1113,9 +1009,6 @@ SetTheImage (
|
|||
UINT32 LowestSupportedVersion;
|
||||
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
|
||||
UINT32 DependenciesSize;
|
||||
BOOLEAN IsDepexValid;
|
||||
UINT8 *ImageBuffer;
|
||||
UINTN ImageBufferSize;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Updateable = 0;
|
||||
|
@ -1128,8 +1021,6 @@ SetTheImage (
|
|||
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
|
||||
Dependencies = NULL;
|
||||
DependenciesSize = 0;
|
||||
ImageBuffer = NULL;
|
||||
ImageBufferSize = 0;
|
||||
|
||||
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
|
@ -1161,11 +1052,6 @@ SetTheImage (
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Set check status to satisfied before CheckTheImage()
|
||||
//
|
||||
mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;
|
||||
|
||||
//
|
||||
// Call check image to verify the image
|
||||
//
|
||||
|
@ -1178,32 +1064,22 @@ SetTheImage (
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the dependency from Image.
|
||||
//
|
||||
Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
|
||||
|
||||
//
|
||||
// No functional error in CheckTheImage. Attempt to get the Version to
|
||||
// support better error reporting.
|
||||
//
|
||||
FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &FmpPayloadSize );
|
||||
FmpHeader = GetFmpHeader ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, DependenciesSize, &FmpPayloadSize );
|
||||
if (FmpHeader == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
|
||||
Status = EFI_ABORTED;
|
||||
goto cleanup;
|
||||
}
|
||||
Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Check if there is dependency expression
|
||||
//
|
||||
IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpHeader, FmpPayloadSize, &DependenciesSize);
|
||||
if (IsDepexValid && (DependenciesSize < FmpPayloadSize)) {
|
||||
//
|
||||
// Fmp payload is after dependency expression
|
||||
//
|
||||
Dependencies = (EFI_FIRMWARE_IMAGE_DEP*) FmpHeader;
|
||||
FmpHeader = (UINT8 *) FmpHeader + DependenciesSize;
|
||||
FmpPayloadSize = FmpPayloadSize - DependenciesSize;
|
||||
Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
|
||||
}
|
||||
}
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Set to actual value
|
||||
|
@ -1218,10 +1094,8 @@ SetTheImage (
|
|||
"FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
|
||||
mImageIdName, Updateable)
|
||||
);
|
||||
if (mDependenciesCheckStatus == DEPENDENCIES_UNSATISFIED) {
|
||||
if (Private->DependenciesSatisfied == FALSE) {
|
||||
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
|
||||
} else if (mDependenciesCheckStatus == DEPENDENCIES_INVALID) {
|
||||
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
|
||||
}
|
||||
Status = EFI_ABORTED;
|
||||
goto cleanup;
|
||||
|
@ -1323,34 +1197,6 @@ SetTheImage (
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
|
||||
//
|
||||
if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
|
||||
//
|
||||
// To support saving dependency, extend param "Image" of FmpDeviceSetImage() to
|
||||
// contain the dependency inside. FmpDeviceSetImage() is responsible for saving
|
||||
// the dependency which can be used for future dependency check.
|
||||
//
|
||||
ImageBufferSize = DependenciesSize + ImageSize - AllHeaderSize;
|
||||
ImageBuffer = AllocatePool (ImageBufferSize);
|
||||
if (ImageBuffer == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));
|
||||
Status = EFI_ABORTED;
|
||||
goto cleanup;
|
||||
}
|
||||
CopyMem (ImageBuffer, Dependencies->Dependencies, DependenciesSize);
|
||||
CopyMem (ImageBuffer + DependenciesSize, (UINT8 *)Image + AllHeaderSize, ImageBufferSize - DependenciesSize);
|
||||
} else {
|
||||
ImageBufferSize = ImageSize - AllHeaderSize;
|
||||
ImageBuffer = AllocateCopyPool(ImageBufferSize, (UINT8 *)Image + AllHeaderSize);
|
||||
if (ImageBuffer == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - AllocatePool failed.\n", mImageIdName));
|
||||
Status = EFI_ABORTED;
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Indicate that control is handed off to FmpDeviceLib
|
||||
//
|
||||
|
@ -1360,8 +1206,8 @@ SetTheImage (
|
|||
//Copy the requested image to the firmware using the FmpDeviceLib
|
||||
//
|
||||
Status = FmpDeviceSetImage (
|
||||
ImageBuffer,
|
||||
ImageBufferSize,
|
||||
(((UINT8 *)Image) + AllHeaderSize),
|
||||
ImageSize - AllHeaderSize,
|
||||
VendorCode,
|
||||
FmpDxeProgress,
|
||||
IncomingFwVersion,
|
||||
|
@ -1372,6 +1218,16 @@ SetTheImage (
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
//
|
||||
// Store the dependency
|
||||
//
|
||||
if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
|
||||
Status = SaveFmpDependency (Dependencies, DependenciesSize);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SaveFmpDependency from FmpDependencyCheckLib failed. (%r)\n", mImageIdName, Status));
|
||||
}
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Finished the update without error
|
||||
|
@ -1398,10 +1254,6 @@ SetTheImage (
|
|||
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
if (ImageBuffer != NULL) {
|
||||
FreePool (ImageBuffer);
|
||||
}
|
||||
|
||||
mProgressFunc = NULL;
|
||||
SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
|
||||
|
||||
|
|
|
@ -28,6 +28,9 @@
|
|||
#include <Library/FmpDeviceLib.h>
|
||||
#include <Library/FmpPayloadHeaderLib.h>
|
||||
#include <Library/CapsuleUpdatePolicyLib.h>
|
||||
#include <Library/FmpDependencyLib.h>
|
||||
#include <Library/FmpDependencyCheckLib.h>
|
||||
#include <Library/FmpDependencyDeviceLib.h>
|
||||
#include <Protocol/FirmwareManagement.h>
|
||||
#include <Protocol/FirmwareManagementProgress.h>
|
||||
#include <Protocol/VariableLock.h>
|
||||
|
@ -66,6 +69,7 @@ typedef struct {
|
|||
CHAR16 *LastAttemptStatusVariableName;
|
||||
CHAR16 *LastAttemptVersionVariableName;
|
||||
CHAR16 *FmpStateVariableName;
|
||||
BOOLEAN DependenciesSatisfied;
|
||||
} FIRMWARE_MANAGEMENT_PRIVATE_DATA;
|
||||
|
||||
///
|
||||
|
|
|
@ -28,8 +28,6 @@
|
|||
[Sources]
|
||||
FmpDxe.c
|
||||
FmpDxe.h
|
||||
Dependency.c
|
||||
Dependency.h
|
||||
DetectTestKey.c
|
||||
VariableSupport.h
|
||||
VariableSupport.c
|
||||
|
@ -54,6 +52,9 @@
|
|||
FmpDeviceLib
|
||||
FmpPayloadHeaderLib
|
||||
CapsuleUpdatePolicyLib
|
||||
FmpDependencyLib
|
||||
FmpDependencyCheckLib
|
||||
FmpDependencyDeviceLib
|
||||
|
||||
[Guids]
|
||||
gEfiEndOfDxeEventGroupGuid
|
||||
|
|
|
@ -29,8 +29,6 @@
|
|||
[Sources]
|
||||
FmpDxe.c
|
||||
FmpDxe.h
|
||||
Dependency.c
|
||||
Dependency.h
|
||||
DetectTestKey.c
|
||||
VariableSupport.h
|
||||
VariableSupport.c
|
||||
|
@ -54,6 +52,9 @@
|
|||
FmpDeviceLib
|
||||
FmpPayloadHeaderLib
|
||||
CapsuleUpdatePolicyLib
|
||||
FmpDependencyLib
|
||||
FmpDependencyCheckLib
|
||||
FmpDependencyDeviceLib
|
||||
|
||||
[Guids]
|
||||
gEfiEndOfDxeEventGroupGuid
|
||||
|
|
Loading…
Reference in New Issue