Files
system76-edk2/FmpDevicePkg/Library/FmpDependencyCheckLib/FmpDependencyCheckLib.c
Michael Kubacki e4e27351e8 FmpDevicePkg/FmpDependencyCheckLib: Return unsatisfied on handle failure
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>
2020-08-07 02:30:01 +00:00

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;
}