mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-29 16:44:10 +02:00
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 "FmpDxe.h"
|
||||||
#include "VariableSupport.h"
|
#include "VariableSupport.h"
|
||||||
#include "Dependency.h"
|
|
||||||
|
|
||||||
///
|
///
|
||||||
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
|
/// 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, // LsvVariableName
|
||||||
NULL, // LastAttemptStatusVariableName
|
NULL, // LastAttemptStatusVariableName
|
||||||
NULL, // LastAttemptVersionVariableName
|
NULL, // LastAttemptVersionVariableName
|
||||||
NULL // FmpStateVariableName
|
NULL, // FmpStateVariableName
|
||||||
|
TRUE // DependenciesSatisfied
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -276,13 +276,7 @@ PopulateDescriptor (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
VOID *Image;
|
UINT32 DependenciesSize;
|
||||||
UINTN ImageSize;
|
|
||||||
BOOLEAN IsDepexValid;
|
|
||||||
UINT32 DepexSize;
|
|
||||||
|
|
||||||
Image = NULL;
|
|
||||||
ImageSize = 0;
|
|
||||||
|
|
||||||
if (Private->DescriptorPopulated) {
|
if (Private->DescriptorPopulated) {
|
||||||
return;
|
return;
|
||||||
@ -387,46 +381,18 @@ PopulateDescriptor (
|
|||||||
Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);
|
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;
|
Private->Descriptor.Dependencies = NULL;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
|
// Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
|
||||||
//
|
//
|
||||||
if (Private->Descriptor.AttributesSupported & IMAGE_ATTRIBUTE_DEPENDENCY) {
|
if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
|
||||||
//
|
Private->Descriptor.Dependencies = GetFmpDependency (&DependenciesSize);
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Private->DescriptorPopulated = TRUE;
|
Private->DescriptorPopulated = TRUE;
|
||||||
|
|
||||||
if (Image != NULL) {
|
|
||||||
FreePool (Image);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -588,17 +554,12 @@ GetTheImage (
|
|||||||
EFI_STATUS Status;
|
EFI_STATUS Status;
|
||||||
FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
|
FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
|
||||||
UINTN Size;
|
UINTN Size;
|
||||||
UINT8 *ImageBuffer;
|
|
||||||
UINTN ImageBufferSize;
|
|
||||||
UINT32 DepexSize;
|
|
||||||
|
|
||||||
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
|
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
ImageBuffer = NULL;
|
|
||||||
DepexSize = 0;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Retrieve the private context structure
|
// Retrieve the private context structure
|
||||||
@ -628,45 +589,8 @@ GetTheImage (
|
|||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
Size = 0;
|
Size = 0;
|
||||||
}
|
}
|
||||||
|
if (*ImageSize < Size) {
|
||||||
//
|
*ImageSize = Size;
|
||||||
// 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;
|
|
||||||
DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));
|
DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));
|
||||||
Status = EFI_BUFFER_TOO_SMALL;
|
Status = EFI_BUFFER_TOO_SMALL;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -678,17 +602,8 @@ GetTheImage (
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
Status = FmpDeviceGetImage (Image, ImageSize);
|
||||||
// Image is after the dependency expression.
|
|
||||||
//
|
|
||||||
*ImageSize = ImageBufferSize - DepexSize;
|
|
||||||
CopyMem (Image, ImageBuffer + DepexSize, *ImageSize);
|
|
||||||
Status = EFI_SUCCESS;
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (ImageBuffer != NULL) {
|
|
||||||
FreePool (ImageBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
@ -697,8 +612,9 @@ cleanup:
|
|||||||
Helper function to safely retrieve the FMP header from
|
Helper function to safely retrieve the FMP header from
|
||||||
within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
|
within an EFI_FIRMWARE_IMAGE_AUTHENTICATION structure.
|
||||||
|
|
||||||
@param[in] Image Pointer to the image.
|
@param[in] Image Pointer to the image.
|
||||||
@param[in] ImageSize Size of 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
|
@param[out] PayloadSize
|
||||||
|
|
||||||
@retval !NULL Valid pointer to the header.
|
@retval !NULL Valid pointer to the header.
|
||||||
@ -709,22 +625,23 @@ VOID *
|
|||||||
GetFmpHeader (
|
GetFmpHeader (
|
||||||
IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
|
IN CONST EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
|
||||||
IN CONST UINTN ImageSize,
|
IN CONST UINTN ImageSize,
|
||||||
|
IN CONST UINTN AdditionalHeaderSize,
|
||||||
OUT UINTN *PayloadSize
|
OUT UINTN *PayloadSize
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
// Check to make sure that operation can be safely performed.
|
// Check to make sure that operation can be safely performed.
|
||||||
//
|
//
|
||||||
if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) < (UINTN)Image || \
|
if (((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize < (UINTN)Image || \
|
||||||
((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) >= (UINTN)Image + ImageSize) {
|
((UINTN)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength) + AdditionalHeaderSize >= (UINTN)Image + ImageSize) {
|
||||||
//
|
//
|
||||||
// Pointer overflow. Invalid image.
|
// Pointer overflow. Invalid image.
|
||||||
//
|
//
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*PayloadSize = ImageSize - (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);
|
return (VOID *)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength + AdditionalHeaderSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -811,8 +728,6 @@ CheckTheImage (
|
|||||||
UINT8 *PublicKeyDataXdrEnd;
|
UINT8 *PublicKeyDataXdrEnd;
|
||||||
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
|
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
|
||||||
UINT32 DependenciesSize;
|
UINT32 DependenciesSize;
|
||||||
BOOLEAN IsDepexValid;
|
|
||||||
BOOLEAN IsDepexSatisfied;
|
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
RawSize = 0;
|
RawSize = 0;
|
||||||
@ -850,6 +765,11 @@ CheckTheImage (
|
|||||||
//
|
//
|
||||||
*ImageUpdatable = IMAGE_UPDATABLE_VALID;
|
*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) {
|
if (Image == NULL) {
|
||||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
|
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
|
||||||
//
|
//
|
||||||
@ -935,11 +855,15 @@ CheckTheImage (
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Get the dependency from Image.
|
||||||
|
//
|
||||||
|
Dependencies = GetImageDependency ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, ImageSize, &DependenciesSize);
|
||||||
|
|
||||||
//
|
//
|
||||||
// Check the FmpPayloadHeader
|
// 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) {
|
if (FmpPayloadHeader == NULL) {
|
||||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
|
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
|
||||||
Status = EFI_ABORTED;
|
Status = EFI_ABORTED;
|
||||||
@ -947,33 +871,10 @@ CheckTheImage (
|
|||||||
}
|
}
|
||||||
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
|
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
|
||||||
if (EFI_ERROR (Status)) {
|
if (EFI_ERROR (Status)) {
|
||||||
//
|
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
|
||||||
// Check if there is dependency expression
|
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
||||||
//
|
Status = EFI_SUCCESS;
|
||||||
IsDepexValid = ValidateImageDepex ((EFI_FIRMWARE_IMAGE_DEP*) FmpPayloadHeader, FmpPayloadSize, &DependenciesSize);
|
goto cleanup;
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -993,14 +894,9 @@ CheckTheImage (
|
|||||||
//
|
//
|
||||||
// Evaluate dependency expression
|
// Evaluate dependency expression
|
||||||
//
|
//
|
||||||
Status = EvaluateImageDependencies (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize, &IsDepexSatisfied);
|
Private->DependenciesSatisfied = CheckFmpDependency (Private->Descriptor.ImageTypeId, Version, Dependencies, DependenciesSize);
|
||||||
if (!IsDepexSatisfied || EFI_ERROR (Status)) {
|
if (!Private->DependenciesSatisfied) {
|
||||||
if (EFI_ERROR (Status)) {
|
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Dependency check failed.\n", mImageIdName));
|
||||||
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;
|
|
||||||
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -1113,9 +1009,6 @@ SetTheImage (
|
|||||||
UINT32 LowestSupportedVersion;
|
UINT32 LowestSupportedVersion;
|
||||||
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
|
EFI_FIRMWARE_IMAGE_DEP *Dependencies;
|
||||||
UINT32 DependenciesSize;
|
UINT32 DependenciesSize;
|
||||||
BOOLEAN IsDepexValid;
|
|
||||||
UINT8 *ImageBuffer;
|
|
||||||
UINTN ImageBufferSize;
|
|
||||||
|
|
||||||
Status = EFI_SUCCESS;
|
Status = EFI_SUCCESS;
|
||||||
Updateable = 0;
|
Updateable = 0;
|
||||||
@ -1128,8 +1021,6 @@ SetTheImage (
|
|||||||
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
|
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
|
||||||
Dependencies = NULL;
|
Dependencies = NULL;
|
||||||
DependenciesSize = 0;
|
DependenciesSize = 0;
|
||||||
ImageBuffer = NULL;
|
|
||||||
ImageBufferSize = 0;
|
|
||||||
|
|
||||||
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
|
if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
@ -1161,11 +1052,6 @@ SetTheImage (
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Set check status to satisfied before CheckTheImage()
|
|
||||||
//
|
|
||||||
mDependenciesCheckStatus = DEPENDENCIES_SATISFIED;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Call check image to verify the image
|
// Call check image to verify the image
|
||||||
//
|
//
|
||||||
@ -1178,32 +1064,22 @@ SetTheImage (
|
|||||||
goto cleanup;
|
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
|
// No functional error in CheckTheImage. Attempt to get the Version to
|
||||||
// support better error reporting.
|
// 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) {
|
if (FmpHeader == NULL) {
|
||||||
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
|
DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
|
||||||
Status = EFI_ABORTED;
|
Status = EFI_ABORTED;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
|
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)) {
|
if (!EFI_ERROR (Status)) {
|
||||||
//
|
//
|
||||||
// Set to actual value
|
// 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",
|
"FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
|
||||||
mImageIdName, Updateable)
|
mImageIdName, Updateable)
|
||||||
);
|
);
|
||||||
if (mDependenciesCheckStatus == DEPENDENCIES_UNSATISFIED) {
|
if (Private->DependenciesSatisfied == FALSE) {
|
||||||
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
|
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
|
||||||
} else if (mDependenciesCheckStatus == DEPENDENCIES_INVALID) {
|
|
||||||
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_INVALID_FORMAT;
|
|
||||||
}
|
}
|
||||||
Status = EFI_ABORTED;
|
Status = EFI_ABORTED;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -1323,34 +1197,6 @@ SetTheImage (
|
|||||||
goto cleanup;
|
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
|
// Indicate that control is handed off to FmpDeviceLib
|
||||||
//
|
//
|
||||||
@ -1360,8 +1206,8 @@ SetTheImage (
|
|||||||
//Copy the requested image to the firmware using the FmpDeviceLib
|
//Copy the requested image to the firmware using the FmpDeviceLib
|
||||||
//
|
//
|
||||||
Status = FmpDeviceSetImage (
|
Status = FmpDeviceSetImage (
|
||||||
ImageBuffer,
|
(((UINT8 *)Image) + AllHeaderSize),
|
||||||
ImageBufferSize,
|
ImageSize - AllHeaderSize,
|
||||||
VendorCode,
|
VendorCode,
|
||||||
FmpDxeProgress,
|
FmpDxeProgress,
|
||||||
IncomingFwVersion,
|
IncomingFwVersion,
|
||||||
@ -1372,6 +1218,16 @@ SetTheImage (
|
|||||||
goto cleanup;
|
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
|
// Finished the update without error
|
||||||
@ -1398,10 +1254,6 @@ SetTheImage (
|
|||||||
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
|
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (ImageBuffer != NULL) {
|
|
||||||
FreePool (ImageBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
mProgressFunc = NULL;
|
mProgressFunc = NULL;
|
||||||
SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
|
SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
|
||||||
|
|
||||||
|
@ -28,6 +28,9 @@
|
|||||||
#include <Library/FmpDeviceLib.h>
|
#include <Library/FmpDeviceLib.h>
|
||||||
#include <Library/FmpPayloadHeaderLib.h>
|
#include <Library/FmpPayloadHeaderLib.h>
|
||||||
#include <Library/CapsuleUpdatePolicyLib.h>
|
#include <Library/CapsuleUpdatePolicyLib.h>
|
||||||
|
#include <Library/FmpDependencyLib.h>
|
||||||
|
#include <Library/FmpDependencyCheckLib.h>
|
||||||
|
#include <Library/FmpDependencyDeviceLib.h>
|
||||||
#include <Protocol/FirmwareManagement.h>
|
#include <Protocol/FirmwareManagement.h>
|
||||||
#include <Protocol/FirmwareManagementProgress.h>
|
#include <Protocol/FirmwareManagementProgress.h>
|
||||||
#include <Protocol/VariableLock.h>
|
#include <Protocol/VariableLock.h>
|
||||||
@ -66,6 +69,7 @@ typedef struct {
|
|||||||
CHAR16 *LastAttemptStatusVariableName;
|
CHAR16 *LastAttemptStatusVariableName;
|
||||||
CHAR16 *LastAttemptVersionVariableName;
|
CHAR16 *LastAttemptVersionVariableName;
|
||||||
CHAR16 *FmpStateVariableName;
|
CHAR16 *FmpStateVariableName;
|
||||||
|
BOOLEAN DependenciesSatisfied;
|
||||||
} FIRMWARE_MANAGEMENT_PRIVATE_DATA;
|
} FIRMWARE_MANAGEMENT_PRIVATE_DATA;
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -28,8 +28,6 @@
|
|||||||
[Sources]
|
[Sources]
|
||||||
FmpDxe.c
|
FmpDxe.c
|
||||||
FmpDxe.h
|
FmpDxe.h
|
||||||
Dependency.c
|
|
||||||
Dependency.h
|
|
||||||
DetectTestKey.c
|
DetectTestKey.c
|
||||||
VariableSupport.h
|
VariableSupport.h
|
||||||
VariableSupport.c
|
VariableSupport.c
|
||||||
@ -54,6 +52,9 @@
|
|||||||
FmpDeviceLib
|
FmpDeviceLib
|
||||||
FmpPayloadHeaderLib
|
FmpPayloadHeaderLib
|
||||||
CapsuleUpdatePolicyLib
|
CapsuleUpdatePolicyLib
|
||||||
|
FmpDependencyLib
|
||||||
|
FmpDependencyCheckLib
|
||||||
|
FmpDependencyDeviceLib
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
gEfiEndOfDxeEventGroupGuid
|
gEfiEndOfDxeEventGroupGuid
|
||||||
|
@ -29,8 +29,6 @@
|
|||||||
[Sources]
|
[Sources]
|
||||||
FmpDxe.c
|
FmpDxe.c
|
||||||
FmpDxe.h
|
FmpDxe.h
|
||||||
Dependency.c
|
|
||||||
Dependency.h
|
|
||||||
DetectTestKey.c
|
DetectTestKey.c
|
||||||
VariableSupport.h
|
VariableSupport.h
|
||||||
VariableSupport.c
|
VariableSupport.c
|
||||||
@ -54,6 +52,9 @@
|
|||||||
FmpDeviceLib
|
FmpDeviceLib
|
||||||
FmpPayloadHeaderLib
|
FmpPayloadHeaderLib
|
||||||
CapsuleUpdatePolicyLib
|
CapsuleUpdatePolicyLib
|
||||||
|
FmpDependencyLib
|
||||||
|
FmpDependencyCheckLib
|
||||||
|
FmpDependencyDeviceLib
|
||||||
|
|
||||||
[Guids]
|
[Guids]
|
||||||
gEfiEndOfDxeEventGroupGuid
|
gEfiEndOfDxeEventGroupGuid
|
||||||
|
Loading…
x
Reference in New Issue
Block a user