From 0f30087b9a2ce4fd21e318c87bee1a129523a194 Mon Sep 17 00:00:00 2001 From: Wei6 Xu Date: Tue, 12 May 2020 13:33:54 +0800 Subject: [PATCH] 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 Cc: Liming Gao Cc: Sean Brogan Signed-off-by: Wei6 Xu Reviewed-by: Sean Brogan Reviewed-by: Liming Gao --- FmpDevicePkg/FmpDxe/Dependency.c | 679 ------------------------------ FmpDevicePkg/FmpDxe/Dependency.h | 63 --- FmpDevicePkg/FmpDxe/FmpDxe.c | 256 +++-------- FmpDevicePkg/FmpDxe/FmpDxe.h | 4 + FmpDevicePkg/FmpDxe/FmpDxe.inf | 5 +- FmpDevicePkg/FmpDxe/FmpDxeLib.inf | 5 +- 6 files changed, 64 insertions(+), 948 deletions(-) delete mode 100644 FmpDevicePkg/FmpDxe/Dependency.c delete mode 100644 FmpDevicePkg/FmpDxe/Dependency.h diff --git a/FmpDevicePkg/FmpDxe/Dependency.c b/FmpDevicePkg/FmpDxe/Dependency.c deleted file mode 100644 index 65c23989c6..0000000000 --- a/FmpDevicePkg/FmpDxe/Dependency.c +++ /dev/null @@ -1,679 +0,0 @@ -/** @file - Supports Capsule Dependency Expression. - - Copyright (c) 2020, Intel Corporation. All rights reserved.
- - 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; -} diff --git a/FmpDevicePkg/FmpDxe/Dependency.h b/FmpDevicePkg/FmpDxe/Dependency.h deleted file mode 100644 index badd2542d6..0000000000 --- a/FmpDevicePkg/FmpDxe/Dependency.h +++ /dev/null @@ -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.
- - SPDX-License-Identifier: BSD-2-Clause-Patent - -**/ - -#ifndef __DEPENDENCY_H__ -#define __DEPENDENCY_H__ - -#include -#include - -#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 diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c index 5b523291e4..58841774fe 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxe.c +++ b/FmpDevicePkg/FmpDxe/FmpDxe.c @@ -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); diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.h b/FmpDevicePkg/FmpDxe/FmpDxe.h index 150f18b656..30754dea49 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxe.h +++ b/FmpDevicePkg/FmpDxe/FmpDxe.h @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -66,6 +69,7 @@ typedef struct { CHAR16 *LastAttemptStatusVariableName; CHAR16 *LastAttemptVersionVariableName; CHAR16 *FmpStateVariableName; + BOOLEAN DependenciesSatisfied; } FIRMWARE_MANAGEMENT_PRIVATE_DATA; /// diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.inf b/FmpDevicePkg/FmpDxe/FmpDxe.inf index 97b6518fa1..eeb904a091 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxe.inf +++ b/FmpDevicePkg/FmpDxe/FmpDxe.inf @@ -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 diff --git a/FmpDevicePkg/FmpDxe/FmpDxeLib.inf b/FmpDevicePkg/FmpDxe/FmpDxeLib.inf index de005b6892..9a93b5e6ac 100644 --- a/FmpDevicePkg/FmpDxe/FmpDxeLib.inf +++ b/FmpDevicePkg/FmpDxe/FmpDxeLib.inf @@ -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 -- 2.39.2