From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.92.42.50]) by mx.groups.io with SMTP id smtpd.web10.5137.1589504352288070127 for ; Thu, 14 May 2020 17:59:12 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@outlook.com header.s=selector1 header.b=Qf7S9A+b; spf=pass (domain: outlook.com, ip: 40.92.42.50, mailfrom: spbrogan@outlook.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=hMUp+plyQ/RYhrknkyRW+v3CbwrWMpMmjRhCBwf4rQXrTNTgx2tNuMKof3SFa4VZwS+bC0AcvQL9GcpHoJh8wz+/j3mSCBVEHHjZL39XlMQy/jWCmAOJXEOLBz1kG2YTyb8GERCVKs6vUunJnOcEQMWDoucHc0Y8upr23IW0M/Yt21BUTIQllGhyHJDCBP0MjI2njxO3gcxUSzh/dmP++t6crUmIcwNrvV+VmM+HjuXeEiKoXo0UyXEXkpQZIhC0UqIYFal+QRW9LGdBMA57RDqzAruFN8IHuQKu777Ec00r6F5sE1s1LQrEN8FafFUW2S/tOS2YgZGzwdbmj4gIfA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=8/IkuT8DfXjCiTZrtjGhmOlczMx72vrw61vGgY+jKWI=; b=F8AiKqdShpvKXvWtNJKmCDL1KG1nMmmeZakdSo4wouMfT/1psuOc6r0k+wHcevXSOXhSJHD8aripvCbrrP3oG2Olto5NR6SCWchspqTjmAlNSOjl0l+YsTV+aEtA1S3e9YFd0Kk5ItysjdhcJvdX41Wf5zX0GJ3s6N+ZkCfs9hbiLKkRjIhFwFsp/DMQGRZACM3tUeULz7zw3gXMmBR+iMkGpWu7auwPW0aa9UGnG5BZUKICJ/rNAHiLgNNhZuswL8yYiRBLpBZ7JOsPLj8zt5VFNjL2x/VoND1MX2/z663XcdJ335omwNhu/0OYrb7HIrIDVdeQLVBbgqpG5zuRmQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=outlook.com; dmarc=pass action=none header.from=outlook.com; dkim=pass header.d=outlook.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=8/IkuT8DfXjCiTZrtjGhmOlczMx72vrw61vGgY+jKWI=; b=Qf7S9A+bylLeabc9wvnAIssoOw0+Y9dPOrUSpZaJv/9/fGHsr8SBXi94w7yazOD54DEWum9WidctQ8lG+GPQx/9UGWgnKSuCrX7ZiiWjhwaMM29yoBjk0HnYX3KaQzqX379u8rGGROu2YRRCBKsbsosaG8juGgwI33c9PC7I4NmN6LEZWcLZSv81HYsxiEhzW1zRuAHfCr1T6P2JfAHYPVvYFOEwD3Eby5xjk7O+8Y4fC6Up6FKSiUFmNCXskoD+1G5UYnd7Fc21xioo+DzQw6CElLMZz0a9pbrw5ArXhZ2ZUZwyNzneDQ77OptQFTuh9LkSPAcvKbx1RCaoXJLEQw== Received: from BN7NAM10FT008.eop-nam10.prod.protection.outlook.com (2a01:111:e400:7e8f::4d) by BN7NAM10HT114.eop-nam10.prod.protection.outlook.com (2a01:111:e400:7e8f::461) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3000.19; Fri, 15 May 2020 00:59:10 +0000 Received: from BN8PR07MB6962.namprd07.prod.outlook.com (2a01:111:e400:7e8f::4c) by BN7NAM10FT008.mail.protection.outlook.com (2a01:111:e400:7e8f::381) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3000.19 via Frontend Transport; Fri, 15 May 2020 00:59:10 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:35D2870FCA2361BDA351486AB8305C4AD930DFB44E4688E440362ACED44840A2;UpperCasedChecksum:6F54DC51EBE367F97AEF6007556FC5600E6E94E5FABC014A0F21B0C59AE3FA55;SizeAsReceived:8951;Count:50 Received: from BN8PR07MB6962.namprd07.prod.outlook.com ([fe80::edbc:7122:7dd9:1403]) by BN8PR07MB6962.namprd07.prod.outlook.com ([fe80::edbc:7122:7dd9:1403%9]) with mapi id 15.20.3000.022; Fri, 15 May 2020 00:59:10 +0000 Subject: Re: [edk2-devel] [PATCH V3 1/5] FmpDevicePkg: Add FmpDependency library class and BASE instance To: devel@edk2.groups.io, wei6.xu@intel.com Cc: Michael D Kinney , Liming Gao , Sean Brogan References: <20200514215232.13372-1-wei6.xu@intel.com> <20200514215232.13372-2-wei6.xu@intel.com> From: "Sean" Message-ID: Date: Thu, 14 May 2020 17:59:07 -0700 User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.8.0 In-Reply-To: <20200514215232.13372-2-wei6.xu@intel.com> X-ClientProxiedBy: CO2PR04CA0169.namprd04.prod.outlook.com (2603:10b6:104:4::23) To BN8PR07MB6962.namprd07.prod.outlook.com (2603:10b6:408:d6::11) Return-Path: spbrogan@outlook.com X-Microsoft-Original-Message-ID: <3001261f-0d84-b2aa-2baa-cc2add8636f4@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 Received: from [192.168.2.78] (50.47.113.221) by CO2PR04CA0169.namprd04.prod.outlook.com (2603:10b6:104:4::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3000.20 via Frontend Transport; Fri, 15 May 2020 00:59:09 +0000 X-Microsoft-Original-Message-ID: <3001261f-0d84-b2aa-2baa-cc2add8636f4@outlook.com> X-TMN: [v9XH7DpYpxc5pLYpiumfj85oJ92nmAtT] X-MS-PublicTrafficType: Email X-IncomingHeaderCount: 50 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-Correlation-Id: c8976e5f-8330-4855-db4a-08d7f86b2d04 X-MS-TrafficTypeDiagnostic: BN7NAM10HT114: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: sHAz9dQ68DR1kH5NmVkxGeaxUEBTB+PjmeYcV/VNLHz0I++aAMkmF3Z4Wiq0dw+eYEWwETCHRqxdZkFhfV98r8qzofHrbLzaI9FBvfPZnLvHd+j3l5D/hjhonw8oicf+EtlpEjMntWCJ2Azy0N0m2+JyJetTLPKIChpcYRhaB7P4yAPJBum4ZeU3/8ypCgGLYL+94Ck/jLtW4aOPGte48+9XcS+xYWE53CHvgv0ZswFxQesW8oK4jDIpoI/GUGDY X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:0;SRV:;IPV:NLI;SFV:NSPM;H:BN8PR07MB6962.namprd07.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:;DIR:OUT;SFP:1901; X-MS-Exchange-AntiSpam-MessageData: fHwsXZsA5Jp+bkll7Iw9Wd2bWp2K8pp0s+Jg9Q0DCGgSvmCPk4cgitfgmjfzcNLpKmn2LYOXaFbAtMOK+Z4n1g3FpBP1Cm9qmFvYhRiZ411YObc2lEncdsHwuUP5Xg+ZcQPb1MZK7K12aoK9Ct6m6w== X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: c8976e5f-8330-4855-db4a-08d7f86b2d04 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 15 May 2020 00:59:10.2849 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN7NAM10HT114 Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit To keep api common please remove the CONST in ValidateDependency function (header and c file). With that change my review applies to the whole series. After this stable tag it would be great to work on some documentation for FmpDxe. This driver was already complex and has now got even more complicated. Reviewed-by: Sean Brogan On 5/14/2020 2:52 PM, Xu, Wei6 wrote: > 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 > Cc: Liming Gao > Cc: Sean Brogan > Signed-off-by: Wei6 Xu > --- > FmpDevicePkg/FmpDevicePkg.dec | 6 +- > FmpDevicePkg/FmpDevicePkg.dsc | 4 +- > FmpDevicePkg/Include/Library/FmpDependencyLib.h | 89 ++++ > .../Library/FmpDependencyLib/FmpDependencyLib.c | 546 +++++++++++++++++++++ > .../Library/FmpDependencyLib/FmpDependencyLib.inf | 34 ++ > .../Library/FmpDependencyLib/FmpDependencyLib.uni | 12 + > 6 files changed, 689 insertions(+), 2 deletions(-) > create mode 100644 FmpDevicePkg/Include/Library/FmpDependencyLib.h > create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c > create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf > create mode 100644 FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni > > diff --git a/FmpDevicePkg/FmpDevicePkg.dec b/FmpDevicePkg/FmpDevicePkg.dec > index 55671878dd..4947008346 100644 > --- a/FmpDevicePkg/FmpDevicePkg.dec > +++ b/FmpDevicePkg/FmpDevicePkg.dec > @@ -5,11 +5,11 @@ > # instance that supports the update of firmware storage devices using UEFI > # Capsules. The behavior of the Firmware Management Protocol instance is > # customized using libraries and PCDs. > # > # Copyright (c) 2016, Microsoft Corporation. All rights reserved.
> -# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
> +# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.
> # > # SPDX-License-Identifier: BSD-2-Clause-Patent > # > ## > > @@ -33,10 +33,14 @@ > > ## @libraryclass Provides firmware device specific services to support > # 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 > # library class. Instead, services are provided to retrieve > # information from the FMP Payload Header. If information is > diff --git a/FmpDevicePkg/FmpDevicePkg.dsc b/FmpDevicePkg/FmpDevicePkg.dsc > index b8fb9d7c19..dfb3c1a141 100644 > --- a/FmpDevicePkg/FmpDevicePkg.dsc > +++ b/FmpDevicePkg/FmpDevicePkg.dsc > @@ -5,11 +5,11 @@ > # instance that supports the update of firmware storage devices using UEFI > # Capsules. The behavior of the Firmware Management Protocol instance is > # customized using libraries and PCDs. > # > # Copyright (c) 2016, Microsoft Corporation. All rights reserved.
> -# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.
> +# Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.
> # Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
> # > # SPDX-License-Identifier: BSD-2-Clause-Patent > # > ## > @@ -58,10 +58,11 @@ > !endif > FmpAuthenticationLib|SecurityPkg/Library/FmpAuthenticationLibPkcs7/FmpAuthenticationLibPkcs7.inf > 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] > # > # It is not possible to prevent the ARM compiler for generic intrinsic functions. > @@ -86,10 +87,11 @@ > # > FmpDevicePkg/Library/CapsuleUpdatePolicyLibNull/CapsuleUpdatePolicyLibNull.inf > FmpDevicePkg/Library/CapsuleUpdatePolicyLibOnProtocol/CapsuleUpdatePolicyLibOnProtocol.inf > FmpDevicePkg/Library/FmpPayloadHeaderLibV1/FmpPayloadHeaderLibV1.inf > FmpDevicePkg/Library/FmpDeviceLibNull/FmpDeviceLibNull.inf > + FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf > FmpDevicePkg/FmpDxe/FmpDxeLib.inf > > # > # Modules > # > diff --git a/FmpDevicePkg/Include/Library/FmpDependencyLib.h b/FmpDevicePkg/Include/Library/FmpDependencyLib.h > new file mode 100644 > index 0000000000..1a191ca6ee > --- /dev/null > +++ b/FmpDevicePkg/Include/Library/FmpDependencyLib.h > @@ -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.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef __FMP_DEPENDENCY_LIB__ > +#define __FMP_DEPENDENCY_LIB__ > + > +#include > +#include > + > +// > +// 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 CONST 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 > diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c > new file mode 100644 > index 0000000000..a8083bff12 > --- /dev/null > +++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.c > @@ -0,0 +1,546 @@ > +/** @file > + Supports Fmp Capsule Dependency Expression. > + > + Copyright (c) 2020, Intel Corporation. All rights reserved.
> + > + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > +#include > +#include > +#include > +#include > +#include > +#include > + > +// > +// 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 CONST 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; > +} > + > diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf > new file mode 100644 > index 0000000000..b7e5c8d002 > --- /dev/null > +++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.inf > @@ -0,0 +1,34 @@ > +## @file > +# Provides Fmp Capsule Dependency Expression support. > +# > +# Copyright (c) 2020, Intel Corporation. All rights reserved.
> +# > +# 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 > diff --git a/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni > new file mode 100644 > index 0000000000..422a96b570 > --- /dev/null > +++ b/FmpDevicePkg/Library/FmpDependencyLib/FmpDependencyLib.uni > @@ -0,0 +1,12 @@ > +// /** @file > +// Provides Fmp Capsule Dependency Expression support. > +// > +// Copyright (c) 2020, Intel Corporation. All rights reserved.
> +// > +// 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." >