mirror of
				https://gitlab.com/qemu-project/edk2.git
				synced 2025-10-30 07:56:39 +08:00 
			
		
		
		
	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:
		| @ -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 | ||||
|  | ||||
|   # | ||||
|  | ||||
							
								
								
									
										89
									
								
								FmpDevicePkg/Include/Library/FmpDependencyLib.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								FmpDevicePkg/Include/Library/FmpDependencyLib.h
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
							
								
								
									
										546
									
								
								FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										546
									
								
								FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
| } | ||||
|  | ||||
							
								
								
									
										34
									
								
								FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
							
								
								
									
										12
									
								
								FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni
									
									
									
									
									
										Normal file
									
								
							| @ -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." | ||||
		Reference in New Issue
	
	Block a user
	 Wei6 Xu
					Wei6 Xu