CheckFmpDependency () will currently return that dependencies are satisfied if the initial call in the function to locate handles that have gEfiFirmwareManagementProtocolGuid installed fails. This change updates the error handling to return FALSE (dependencies are not satisfied) if this handle search fails. Cc: Liming Gao <liming.gao@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Guomin Jiang <guomin.jiang@intel.com> Cc: Wei6 Xu <wei6.xu@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Guomin Jiang <guomin.jiang@intel.com> Reviewed-by: Wei6 Xu <wei6.xu@intel.com>
199 lines
6.1 KiB
C
199 lines
6.1 KiB
C
/** @file
|
|
Provides FMP capsule dependency check services when updating the firmware
|
|
image of a FMP device.
|
|
|
|
Copyright (c) Microsoft Corporation.<BR>
|
|
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/FmpDependencyCheckLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/UefiLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
|
|
/**
|
|
Check dependency for firmware update.
|
|
|
|
@param[in] ImageTypeId Image Type Id.
|
|
@param[in] Version New version.
|
|
@param[in] Dependencies Fmp dependency.
|
|
@param[in] DependenciesSize Size, in bytes, of the Fmp dependency.
|
|
|
|
@retval TRUE Dependencies are satisfied.
|
|
@retval FALSE Dependencies are unsatisfied or dependency check fails.
|
|
|
|
**/
|
|
BOOLEAN
|
|
EFIAPI
|
|
CheckFmpDependency (
|
|
IN EFI_GUID ImageTypeId,
|
|
IN UINT32 Version,
|
|
IN EFI_FIRMWARE_IMAGE_DEP *Dependencies, OPTIONAL
|
|
IN UINT32 DependenciesSize
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_HANDLE *HandleBuffer;
|
|
UINTN Index;
|
|
EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
|
|
UINTN ImageInfoSize;
|
|
UINT32 *DescriptorVer;
|
|
UINT8 FmpImageInfoCount;
|
|
UINTN *DescriptorSize;
|
|
UINT32 PackageVersion;
|
|
CHAR16 *PackageVersionName;
|
|
UINTN NumberOfFmpInstance;
|
|
EFI_FIRMWARE_IMAGE_DESCRIPTOR **FmpImageInfoBuf;
|
|
FMP_DEPEX_CHECK_VERSION_DATA *FmpVersions;
|
|
UINTN FmpVersionsCount;
|
|
BOOLEAN IsSatisfied;
|
|
|
|
FmpImageInfoBuf = NULL;
|
|
DescriptorVer = NULL;
|
|
DescriptorSize = NULL;
|
|
NumberOfFmpInstance = 0;
|
|
FmpVersions = NULL;
|
|
FmpVersionsCount = 0;
|
|
IsSatisfied = TRUE;
|
|
PackageVersionName = NULL;
|
|
|
|
//
|
|
// Get ImageDescriptors of all FMP instances, and archive them for dependency evaluation.
|
|
//
|
|
Status = gBS->LocateHandleBuffer (
|
|
ByProtocol,
|
|
&gEfiFirmwareManagementProtocolGuid,
|
|
NULL,
|
|
&NumberOfFmpInstance,
|
|
&HandleBuffer
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "CheckFmpDependency: Get Firmware Management Protocol failed. (%r)", Status));
|
|
IsSatisfied = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
FmpImageInfoBuf = AllocateZeroPool (sizeof(EFI_FIRMWARE_IMAGE_DESCRIPTOR *) * NumberOfFmpInstance);
|
|
if (FmpImageInfoBuf == NULL) {
|
|
IsSatisfied = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
DescriptorVer = AllocateZeroPool (sizeof(UINT32) * NumberOfFmpInstance);
|
|
if (DescriptorVer == NULL ) {
|
|
IsSatisfied = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
DescriptorSize = AllocateZeroPool (sizeof(UINTN) * NumberOfFmpInstance);
|
|
if (DescriptorSize == NULL ) {
|
|
IsSatisfied = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
FmpVersions = AllocateZeroPool (sizeof(FMP_DEPEX_CHECK_VERSION_DATA) * NumberOfFmpInstance);
|
|
if (FmpVersions == NULL) {
|
|
IsSatisfied = FALSE;
|
|
goto cleanup;
|
|
}
|
|
|
|
for (Index = 0; Index < NumberOfFmpInstance; 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;
|
|
}
|
|
|
|
FmpImageInfoBuf[Index] = AllocateZeroPool (ImageInfoSize);
|
|
if (FmpImageInfoBuf[Index] == NULL) {
|
|
continue;
|
|
}
|
|
|
|
Status = Fmp->GetImageInfo (
|
|
Fmp,
|
|
&ImageInfoSize, // ImageInfoSize
|
|
FmpImageInfoBuf[Index], // ImageInfo
|
|
&DescriptorVer[Index], // DescriptorVersion
|
|
&FmpImageInfoCount, // DescriptorCount
|
|
&DescriptorSize[Index], // DescriptorSize
|
|
&PackageVersion, // PackageVersion
|
|
&PackageVersionName // PackageVersionName
|
|
);
|
|
if (EFI_ERROR(Status)) {
|
|
FreePool (FmpImageInfoBuf[Index]);
|
|
FmpImageInfoBuf[Index] = NULL;
|
|
continue;
|
|
}
|
|
|
|
if (PackageVersionName != NULL) {
|
|
FreePool (PackageVersionName);
|
|
PackageVersionName = NULL;
|
|
}
|
|
|
|
CopyGuid (&FmpVersions[FmpVersionsCount].ImageTypeId, &FmpImageInfoBuf[Index]->ImageTypeId);
|
|
FmpVersions[FmpVersionsCount].Version = FmpImageInfoBuf[Index]->Version;
|
|
FmpVersionsCount ++;
|
|
}
|
|
|
|
//
|
|
// Evaluate firmware image's depex, against the version of other Fmp instances.
|
|
//
|
|
if (Dependencies != NULL) {
|
|
IsSatisfied = EvaluateDependency (Dependencies, DependenciesSize, FmpVersions, FmpVersionsCount);
|
|
}
|
|
|
|
if (!IsSatisfied) {
|
|
DEBUG ((DEBUG_ERROR, "CheckFmpDependency: %g\'s dependency is not satisfied!\n", ImageTypeId));
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if (FmpImageInfoBuf != NULL) {
|
|
for (Index = 0; Index < NumberOfFmpInstance; Index ++) {
|
|
if (FmpImageInfoBuf[Index] != NULL) {
|
|
FreePool (FmpImageInfoBuf[Index]);
|
|
}
|
|
}
|
|
FreePool (FmpImageInfoBuf);
|
|
}
|
|
|
|
if (DescriptorVer != NULL) {
|
|
FreePool (DescriptorVer);
|
|
}
|
|
|
|
if (DescriptorSize != NULL) {
|
|
FreePool (DescriptorSize);
|
|
}
|
|
|
|
if (FmpVersions != NULL) {
|
|
FreePool (FmpVersions);
|
|
}
|
|
|
|
return IsSatisfied;
|
|
}
|