mirror of https://github.com/acidanthera/audk.git
FmpDevicePkg: Add FmpDependency library class and BASE instance
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2696 This library provides services to evaluate Fmp capsule dependency expression, validate dependency expression and get dependency from firmware image. 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
154e243a99
commit
a93bf06b1d
|
@ -7,7 +7,7 @@
|
|||
# customized using libraries and PCDs.
|
||||
#
|
||||
# Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
#
|
||||
|
@ -35,6 +35,10 @@
|
|||
# updates of a firmware image stored in a firmware device.
|
||||
FmpDeviceLib|Include/Library/FmpDeviceLib.h
|
||||
|
||||
## @libraryclass Provides generic services to support capsule dependency
|
||||
# expression evaluation.
|
||||
FmpDependencyLib|Include/Library/FmpDependencyLib.h
|
||||
|
||||
[LibraryClasses.Common.Private]
|
||||
## @libraryclass Provides services to retrieve values from a capsule's FMP
|
||||
# Payload Header. The structure is not included in the
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# customized using libraries and PCDs.
|
||||
#
|
||||
# Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.<BR>
|
||||
# Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
@ -60,6 +60,7 @@
|
|||
CapsuleUpdatePolicyLib|FmpDevicePkg/Library/CapsuleUpdatePolicyLibNull/CapsuleUpdatePolicyLibNull.inf
|
||||
FmpPayloadHeaderLib|FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf
|
||||
FmpDeviceLib|FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLibNull.inf
|
||||
FmpDependencyLib|FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
|
||||
TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
|
||||
|
||||
[LibraryClasses.ARM, LibraryClasses.AARCH64]
|
||||
|
@ -88,6 +89,7 @@
|
|||
FmpDevicePkg/Library/CapsuleUpdatePolicyLibOnProtocol/CapsuleUpdatePolicyLibOnProtocol.inf
|
||||
FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf
|
||||
FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLibNull.inf
|
||||
FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
|
||||
FmpDevicePkg/FmpDxe/FmpDxeLib.inf
|
||||
|
||||
#
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
/** @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 __FMP_DEPENDENCY_LIB__
|
||||
#define __FMP_DEPENDENCY_LIB__
|
||||
|
||||
#include <PiDxe.h>
|
||||
#include <Protocol/FirmwareManagement.h>
|
||||
|
||||
//
|
||||
// Data struct to store FMP ImageType and version for dependency check.
|
||||
//
|
||||
typedef struct {
|
||||
EFI_GUID ImageTypeId;
|
||||
UINT32 Version;
|
||||
} FMP_DEPEX_CHECK_VERSION_DATA;
|
||||
|
||||
/**
|
||||
Validate the dependency expression and output its size.
|
||||
|
||||
@param[in] Dependencies 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
|
||||
EFIAPI
|
||||
ValidateDependency (
|
||||
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
|
||||
IN UINTN MaxDepexSize,
|
||||
OUT UINT32 *DepexSize
|
||||
);
|
||||
|
||||
/**
|
||||
Get dependency from firmware image.
|
||||
|
||||
@param[in] Image Points to the firmware image.
|
||||
@param[in] ImageSize Size, in bytes, of the firmware image.
|
||||
@param[out] DepexSize Size, in bytes, of the dependency.
|
||||
|
||||
@retval The pointer to dependency.
|
||||
@retval Null
|
||||
|
||||
**/
|
||||
EFI_FIRMWARE_IMAGE_DEP*
|
||||
EFIAPI
|
||||
GetImageDependency (
|
||||
IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
|
||||
IN UINTN ImageSize,
|
||||
OUT UINT32 *DepexSize
|
||||
);
|
||||
|
||||
/**
|
||||
Evaluate the dependencies. The caller must search all the Fmp instances and
|
||||
gather their versions into FmpVersions parameter. If there is PUSH_GUID opcode
|
||||
in dependency expression with no FmpVersions provided, the dependency will
|
||||
evaluate to FALSE.
|
||||
|
||||
@param[in] Dependencies Dependency expressions.
|
||||
@param[in] DependenciesSize Size of Dependency expressions.
|
||||
@param[in] FmpVersions Array of Fmp ImageTypeId and version. This
|
||||
parameter is optional and can be set to NULL.
|
||||
@param[in] FmpVersionsCount Element count of the array. When FmpVersions
|
||||
is NULL, FmpVersionsCount must be 0.
|
||||
|
||||
@retval TRUE Dependency expressions evaluate to TRUE.
|
||||
@retval FALSE Dependency expressions evaluate to FALSE.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
EvaluateDependency (
|
||||
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
|
||||
IN UINTN DependenciesSize,
|
||||
IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL,
|
||||
IN UINTN FmpVersionsCount
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,546 @@
|
|||
/** @file
|
||||
Supports Fmp Capsule Dependency Expression.
|
||||
|
||||
Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
#include <PiDxe.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/FmpDependencyLib.h>
|
||||
#include <Library/MemoryAllocationLib.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 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) {
|
||||
DEBUG ((DEBUG_ERROR, "GrowDepexStack: Cannot allocate memory for dependency evaluation stack!\n"));
|
||||
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) {
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: Stack underflow!\n"));
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
//
|
||||
// Pop the item off the stack
|
||||
//
|
||||
mDepexEvaluationStackPointer--;
|
||||
*Element = *mDepexEvaluationStackPointer;
|
||||
if ((*Element).Type != Type) {
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: Popped element type is mismatched!\n"));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Evaluate the dependencies. The caller must search all the Fmp instances and
|
||||
gather their versions into FmpVersions parameter. If there is PUSH_GUID opcode
|
||||
in dependency expression with no FmpVersions provided, the dependency will
|
||||
evaluate to FALSE.
|
||||
|
||||
@param[in] Dependencies Dependency expressions.
|
||||
@param[in] DependenciesSize Size of Dependency expressions.
|
||||
@param[in] FmpVersions Array of Fmp ImageTypeId and version. This
|
||||
parameter is optional and can be set to NULL.
|
||||
@param[in] FmpVersionsCount Element count of the array. When FmpVersions
|
||||
is NULL, FmpVersionsCount must be 0.
|
||||
|
||||
@retval TRUE Dependency expressions evaluate to TRUE.
|
||||
@retval FALSE Dependency expressions evaluate to FALSE.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
EvaluateDependency (
|
||||
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
|
||||
IN UINTN DependenciesSize,
|
||||
IN FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions OPTIONAL,
|
||||
IN UINTN FmpVersionsCount
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *Iterator;
|
||||
UINT8 Index;
|
||||
DEPEX_ELEMENT Element1;
|
||||
DEPEX_ELEMENT Element2;
|
||||
GUID ImageTypeId;
|
||||
UINT32 Version;
|
||||
|
||||
//
|
||||
// Check if parameter is valid.
|
||||
//
|
||||
if (Dependencies == NULL || DependenciesSize == 0) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (FmpVersions == NULL && FmpVersionsCount > 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) {
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: GUID extends beyond end of dependency expression!\n"));
|
||||
goto Error;
|
||||
}
|
||||
|
||||
CopyGuid (&ImageTypeId, (EFI_GUID *) (Iterator + 1));
|
||||
Iterator = Iterator + sizeof (EFI_GUID);
|
||||
|
||||
for (Index = 0; Index < FmpVersionsCount; Index ++) {
|
||||
if(CompareGuid (&FmpVersions[Index].ImageTypeId, &ImageTypeId)){
|
||||
Status = Push (FmpVersions[Index].Version, VersionType);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Index == FmpVersionsCount) {
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: %g is not found!\n", &ImageTypeId));
|
||||
goto Error;
|
||||
}
|
||||
break;
|
||||
case EFI_FMP_DEP_PUSH_VERSION:
|
||||
if (Iterator + sizeof (UINT32) >= (UINT8 *) Dependencies->Dependencies + DependenciesSize ) {
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: VERSION extends beyond end of dependency expression!\n"));
|
||||
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));
|
||||
if (Iterator == (UINT8 *) Dependencies->Dependencies + DependenciesSize) {
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: STRING extends beyond end of dependency expression!\n"));
|
||||
}
|
||||
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:
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: Unknown Opcode - %02x!\n", *Iterator));
|
||||
goto Error;
|
||||
}
|
||||
Iterator++;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_ERROR, "EvaluateDependency: No EFI_FMP_DEP_END Opcode in exression!\n"));
|
||||
|
||||
Error:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Validate the dependency expression and output its size.
|
||||
|
||||
@param[in] Dependencies 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
|
||||
EFIAPI
|
||||
ValidateDependency (
|
||||
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies,
|
||||
IN UINTN MaxDepexSize,
|
||||
OUT UINT32 *DepexSize
|
||||
)
|
||||
{
|
||||
UINT8 *Depex;
|
||||
|
||||
if (DepexSize != NULL) {
|
||||
*DepexSize = 0;
|
||||
}
|
||||
|
||||
if (Dependencies == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Depex = Dependencies->Dependencies;
|
||||
while (Depex < Dependencies->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, Dependencies->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;
|
||||
if (DepexSize != NULL) {
|
||||
*DepexSize = (UINT32)(Depex - Dependencies->Dependencies);
|
||||
}
|
||||
return TRUE;
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Get dependency from firmware image.
|
||||
|
||||
@param[in] Image Points to the firmware image.
|
||||
@param[in] ImageSize Size, in bytes, of the firmware image.
|
||||
@param[out] DepexSize Size, in bytes, of the dependency.
|
||||
|
||||
@retval The pointer to dependency.
|
||||
@retval Null
|
||||
|
||||
**/
|
||||
EFI_FIRMWARE_IMAGE_DEP*
|
||||
EFIAPI
|
||||
GetImageDependency (
|
||||
IN EFI_FIRMWARE_IMAGE_AUTHENTICATION *Image,
|
||||
IN UINTN ImageSize,
|
||||
OUT UINT32 *DepexSize
|
||||
)
|
||||
{
|
||||
EFI_FIRMWARE_IMAGE_DEP *Depex;
|
||||
UINTN MaxDepexSize;
|
||||
|
||||
if (Image == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// 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) {
|
||||
//
|
||||
// Pointer overflow. Invalid image.
|
||||
//
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Depex = (EFI_FIRMWARE_IMAGE_DEP*)((UINT8 *)Image + sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
|
||||
MaxDepexSize = ImageSize - (sizeof (Image->MonotonicCount) + Image->AuthInfo.Hdr.dwLength);
|
||||
|
||||
//
|
||||
// Validate the dependency and get the size of dependency
|
||||
//
|
||||
if (ValidateDependency (Depex, MaxDepexSize, DepexSize)) {
|
||||
return Depex;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
## @file
|
||||
# Provides Fmp Capsule Dependency Expression support.
|
||||
#
|
||||
# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = FmpDependencyLib
|
||||
MODULE_UNI_FILE = FmpDependencyLib.uni
|
||||
FILE_GUID = 67F55EA4-B4CF-4A08-931B-0BBCF1E0F7A3
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = FmpDependencyLib
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 ARM AARCH64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
FmpDependencyLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
FmpDevicePkg/FmpDevicePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DebugLib
|
||||
BaseMemoryLib
|
|
@ -0,0 +1,12 @@
|
|||
// /** @file
|
||||
// Provides Fmp Capsule Dependency Expression support.
|
||||
//
|
||||
// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "FMP Dependency Lib"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "Provides Fmp Capsule Dependency Expression support."
|
Loading…
Reference in New Issue