X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=FmpDevicePkg%2FFmpDxe%2FFmpDxe.c;h=58841774fee023ece7ce9549d9fe0ccaa780aa68;hb=0f30087b9a2ce4fd21e318c87bee1a129523a194;hp=3794ac5008f95ecc51cb881540e745e62fa3782e;hpb=27e42bf61bb27a61b5b4dd053c6bc219c73c4cc8;p=mirror_edk2.git
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index 3794ac5008..58841774fe 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -4,64 +4,15 @@
information provided through PCDs and libraries.
Copyright (c) 2016, Microsoft Corporation. All rights reserved.
- Copyright (c) 2018, Intel Corporation. All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
- OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
+#include "FmpDxe.h"
#include "VariableSupport.h"
-#define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"
-#define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"
-
-/**
- Check to see if any of the keys in PcdFmpDevicePkcs7CertBufferXdr matches
- the test key. PcdFmpDeviceTestKeySha256Digest contains the SHA256 hash of
- the test key. For each key in PcdFmpDevicePkcs7CertBufferXdr, compute the
- SHA256 hash and compare it to PcdFmpDeviceTestKeySha256Digest. If the
- SHA256 hash matches or there is then error computing the SHA256 hash, then
- set PcdTestKeyUsed to TRUE. Skip this check if PcdTestKeyUsed is already
- TRUE or PcdFmpDeviceTestKeySha256Digest is not exactly SHA256_DIGEST_SIZE
- bytes.
-**/
-VOID
-DetectTestKey (
- VOID
- );
-
///
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
/// FILE_GUID must always be overridden in the section to provide
@@ -73,30 +24,80 @@ const EFI_GUID mDefaultModuleFileGuid = {
0x78ef0a56, 0x1cf0, 0x4535, { 0xb5, 0xda, 0xf6, 0xfd, 0x2f, 0x40, 0x5a, 0x11 }
};
-EFI_FIRMWARE_IMAGE_DESCRIPTOR mDesc;
-BOOLEAN mDescriptorPopulated = FALSE;
-BOOLEAN mRuntimeVersionSupported = TRUE;
-BOOLEAN mFmpInstalled = FALSE;
-
///
-/// Function pointer to progress function
+/// TRUE if FmpDeviceLib manages a single firmware storage device.
///
-EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL;
-BOOLEAN mProgressSupported = FALSE;
+BOOLEAN mFmpSingleInstance = FALSE;
-CHAR16 *mImageIdName = NULL;
-UINT64 mImageId = 0x1;
-CHAR16 *mVersionName = NULL;
+///
+/// Firmware Management Protocol instance that is initialized in the entry
+/// point from PCD settings.
+///
+EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL mFmpProgress;
-EFI_EVENT mFmpDeviceLockEvent;
//
-// Indicates if an attempt has been made to lock a
-// FLASH storage device by calling FmpDeviceLock().
-// A FLASH storage device may not support being locked,
-// so this variable is set to TRUE even if FmpDeviceLock()
-// returns an error.
+// Template of the private context structure for the Firmware Management
+// Protocol instance
//
-BOOLEAN mFmpDeviceLocked = FALSE;
+const FIRMWARE_MANAGEMENT_PRIVATE_DATA mFirmwareManagementPrivateDataTemplate = {
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE, // Signature
+ NULL, // Handle
+ { // Fmp
+ GetTheImageInfo,
+ GetTheImage,
+ SetTheImage,
+ CheckTheImage,
+ GetPackageInfo,
+ SetPackageInfo
+ },
+ FALSE, // DescriptorPopulated
+ { // Desc
+ 1, // ImageIndex
+ //
+ // ImageTypeId
+ //
+ { 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} },
+ 1, // ImageId
+ NULL, // ImageIdName
+ 0, // Version
+ NULL, // VersionName
+ 0, // Size
+ 0, // AttributesSupported
+ 0, // AttributesSetting
+ 0, // Compatibilities
+ 0, // LowestSupportedImageVersion
+ 0, // LastAttemptVersion
+ 0, // LastAttemptStatus
+ 0 // HardwareInstance
+ },
+ NULL, // ImageIdName
+ NULL, // VersionName
+ TRUE, // RuntimeVersionSupported
+ NULL, // FmpDeviceLockEvent
+ FALSE, // FmpDeviceLocked
+ NULL, // FmpDeviceContext
+ NULL, // VersionVariableName
+ NULL, // LsvVariableName
+ NULL, // LastAttemptStatusVariableName
+ NULL, // LastAttemptVersionVariableName
+ NULL, // FmpStateVariableName
+ TRUE // DependenciesSatisfied
+};
+
+///
+/// GUID that is used to create event used to lock the firmware storage device.
+///
+EFI_GUID *mLockGuid = NULL;
+
+///
+/// Progress() function pointer passed into SetTheImage()
+///
+EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS mProgressFunc = NULL;
+
+///
+/// Null-terminated Unicode string retrieved from PcdFmpDeviceImageIdName.
+///
+CHAR16 *mImageIdName = NULL;
/**
Callback function to report the process of the firmware updating.
@@ -128,10 +129,6 @@ FmpDxeProgress (
Status = EFI_UNSUPPORTED;
- if (!mProgressSupported) {
- return Status;
- }
-
if (mProgressFunc == NULL) {
return Status;
}
@@ -142,7 +139,6 @@ FmpDxeProgress (
Status = mProgressFunc (((Completion * 92) / 100) + 6);
if (Status == EFI_UNSUPPORTED) {
- mProgressSupported = FALSE;
mProgressFunc = NULL;
}
@@ -152,9 +148,11 @@ FmpDxeProgress (
/**
Returns a pointer to the ImageTypeId GUID value. An attempt is made to get
the GUID value from the FmpDeviceLib. If the FmpDeviceLib does not provide
- a GUID value, then gEfiCallerIdGuid is returned.
+ a GUID value, then PcdFmpDeviceImageTypeIdGuid is used. If the size of
+ PcdFmpDeviceImageTypeIdGuid is not the size of EFI_GUID, then gEfiCallerIdGuid
+ is returned.
- @return The ImageTypeId GUID
+ @retval The ImageTypeId GUID
**/
EFI_GUID *
@@ -164,18 +162,26 @@ GetImageTypeIdGuid (
{
EFI_STATUS Status;
EFI_GUID *FmpDeviceLibGuid;
+ UINTN ImageTypeIdGuidSize;
FmpDeviceLibGuid = NULL;
Status = FmpDeviceGetImageTypeIdGuidPtr (&FmpDeviceLibGuid);
if (EFI_ERROR (Status)) {
if (Status != EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid error %r\n", mImageIdName, Status));
}
- return &gEfiCallerIdGuid;
+ } else if (FmpDeviceLibGuid == NULL) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n", mImageIdName));
+ Status = EFI_NOT_FOUND;
}
- if (FmpDeviceLibGuid == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib GetImageTypeIdGuidPtr() returned invalid GUID\n"));
- return &gEfiCallerIdGuid;
+ if (EFI_ERROR (Status)) {
+ ImageTypeIdGuidSize = PcdGetSize (PcdFmpDeviceImageTypeIdGuid);
+ if (ImageTypeIdGuidSize == sizeof (EFI_GUID)) {
+ FmpDeviceLibGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceImageTypeIdGuid);
+ } else {
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): Fall back to ImageTypeIdGuid of gEfiCallerIdGuid\n", mImageIdName));
+ FmpDeviceLibGuid = &gEfiCallerIdGuid;
+ }
}
return FmpDeviceLibGuid;
}
@@ -183,7 +189,7 @@ GetImageTypeIdGuid (
/**
Returns a pointer to the Null-terminated Unicode ImageIdName string.
- @return Null-terminated Unicode ImageIdName string.
+ @retval Null-terminated Unicode ImageIdName string.
**/
CHAR16 *
@@ -200,12 +206,15 @@ GetImageTypeNameString (
2. Check if we have a variable for lowest supported version (this will be updated with each capsule applied)
3. Check Fixed at build PCD
- Take the largest value
+ @param[in] Private Pointer to the private context structure for the
+ Firmware Management Protocol instance.
+
+ @retval The largest value
**/
UINT32
GetLowestSupportedVersion (
- VOID
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
@@ -242,7 +251,7 @@ GetLowestSupportedVersion (
//
// Check the lowest supported version UEFI variable for this device
//
- VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable();
+ VariableLowestSupportedVersion = GetLowestSupportedVersionFromVariable (Private);
if (VariableLowestSupportedVersion > ReturnLsv) {
ReturnLsv = VariableLowestSupportedVersion;
}
@@ -254,101 +263,136 @@ GetLowestSupportedVersion (
}
/**
- Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the module global
- variable mDesc.
+ Populates the EFI_FIRMWARE_IMAGE_DESCRIPTOR structure in the private
+ context structure.
+
+ @param[in] Private Pointer to the private context structure for the
+ Firmware Management Protocol instance.
**/
VOID
PopulateDescriptor (
- VOID
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private
)
{
EFI_STATUS Status;
+ UINT32 DependenciesSize;
- mDesc.ImageIndex = 1;
- CopyGuid (&mDesc.ImageTypeId, GetImageTypeIdGuid());
- mDesc.ImageId = mImageId;
- mDesc.ImageIdName = GetImageTypeNameString();
+ if (Private->DescriptorPopulated) {
+ return;
+ }
+
+ Private->Descriptor.ImageIndex = 1;
+ CopyGuid (&Private->Descriptor.ImageTypeId, GetImageTypeIdGuid());
+ Private->Descriptor.ImageId = Private->Descriptor.ImageIndex;
+ Private->Descriptor.ImageIdName = GetImageTypeNameString();
+
+ //
+ // Get the hardware instance from FmpDeviceLib
+ //
+ Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);
+ if (Status == EFI_UNSUPPORTED) {
+ Private->Descriptor.HardwareInstance = 0;
+ }
+
+ //
+ // Generate UEFI Variable names used to store status information for this
+ // FMP instance.
+ //
+ GenerateFmpVariableNames (Private);
//
// Get the version. Some devices don't support getting the firmware version
// at runtime. If FmpDeviceLib does not support returning a version, then
// it is stored in a UEFI variable.
//
- Status = FmpDeviceGetVersion (&mDesc.Version);
+ Status = FmpDeviceGetVersion (&Private->Descriptor.Version);
if (Status == EFI_UNSUPPORTED) {
- mRuntimeVersionSupported = FALSE;
- mDesc.Version = GetVersionFromVariable();
+ Private->RuntimeVersionSupported = FALSE;
+ Private->Descriptor.Version = GetVersionFromVariable (Private);
} else if (EFI_ERROR (Status)) {
//
// Unexpected error. Use default version.
//
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetVersion() from FmpDeviceLib (%s) returned %r\n", GetImageTypeNameString(), Status));
- mDesc.Version = DEFAULT_VERSION;
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetVersion() from FmpDeviceLib (%s) returned %r\n", mImageIdName, GetImageTypeNameString(), Status));
+ Private->Descriptor.Version = DEFAULT_VERSION;
}
//
// Free the current version name. Shouldn't really happen but this populate
// function could be called multiple times (to refresh).
//
- if (mVersionName != NULL) {
- FreePool (mVersionName);
- mVersionName = NULL;
+ if (Private->Descriptor.VersionName != NULL) {
+ FreePool (Private->Descriptor.VersionName);
+ Private->Descriptor.VersionName = NULL;
}
//
// Attempt to get the version string from the FmpDeviceLib
//
- Status = FmpDeviceGetVersionString (&mVersionName);
+ Status = FmpDeviceGetVersionString (&Private->Descriptor.VersionName);
if (Status == EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() unsupported in FmpDeviceLib.\n"));
- mVersionName = AllocateCopyPool (
- sizeof (VERSION_STRING_NOT_SUPPORTED),
- VERSION_STRING_NOT_SUPPORTED
- );
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() unsupported in FmpDeviceLib.\n", mImageIdName));
+ Private->Descriptor.VersionName = AllocateCopyPool (
+ sizeof (VERSION_STRING_NOT_SUPPORTED),
+ VERSION_STRING_NOT_SUPPORTED
+ );
} else if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_INFO, "FmpDxe: GetVersionString() not available in FmpDeviceLib.\n"));
- mVersionName = AllocateCopyPool (
- sizeof (VERSION_STRING_NOT_AVAILABLE),
- VERSION_STRING_NOT_AVAILABLE
- );
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): GetVersionString() not available in FmpDeviceLib.\n", mImageIdName));
+ Private->Descriptor.VersionName = AllocateCopyPool (
+ sizeof (VERSION_STRING_NOT_AVAILABLE),
+ VERSION_STRING_NOT_AVAILABLE
+ );
}
- mDesc.VersionName = mVersionName;
-
- mDesc.LowestSupportedImageVersion = GetLowestSupportedVersion();
+ Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion (Private);
//
// Get attributes from the FmpDeviceLib
//
- FmpDeviceGetAttributes (&mDesc.AttributesSupported, &mDesc.AttributesSetting);
+ FmpDeviceGetAttributes (
+ &Private->Descriptor.AttributesSupported,
+ &Private->Descriptor.AttributesSetting
+ );
//
// Force set the updatable bits in the attributes;
//
- mDesc.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
- mDesc.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+ Private->Descriptor.AttributesSupported |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
+ Private->Descriptor.AttributesSetting |= IMAGE_ATTRIBUTE_IMAGE_UPDATABLE;
//
// Force set the authentication bits in the attributes;
//
- mDesc.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
- mDesc.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+ Private->Descriptor.AttributesSupported |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
+ Private->Descriptor.AttributesSetting |= (IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED);
- mDesc.Compatibilities = 0;
+ Private->Descriptor.Compatibilities = 0;
//
// Get the size of the firmware image from the FmpDeviceLib
//
- Status = FmpDeviceGetSize (&mDesc.Size);
+ Status = FmpDeviceGetSize (&Private->Descriptor.Size);
if (EFI_ERROR (Status)) {
- mDesc.Size = 0;
+ Private->Descriptor.Size = 0;
}
- mDesc.LastAttemptVersion = GetLastAttemptVersionFromVariable ();
- mDesc.LastAttemptStatus = GetLastAttemptStatusFromVariable ();
+ Private->Descriptor.LastAttemptVersion = GetLastAttemptVersionFromVariable (Private);
+ Private->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable (Private);
- mDescriptorPopulated = TRUE;
+ //
+ // Get the dependency from the FmpDependencyDeviceLib.
+ //
+ Private->Descriptor.Dependencies = NULL;
+
+ //
+ // Check the attribute IMAGE_ATTRIBUTE_DEPENDENCY
+ //
+ if (Private->Descriptor.AttributesSetting & IMAGE_ATTRIBUTE_DEPENDENCY) {
+ Private->Descriptor.Dependencies = GetFmpDependency (&DependenciesSize);
+ }
+
+ Private->DescriptorPopulated = TRUE;
}
/**
@@ -402,15 +446,22 @@ GetTheImageInfo (
OUT CHAR16 **PackageVersionName
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
Status = EFI_SUCCESS;
+ //
+ // Retrieve the private context structure
+ //
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
+
//
// Check for valid pointer
//
if (ImageInfoSize == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - ImageInfoSize is NULL.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
@@ -421,7 +472,7 @@ GetTheImageInfo (
//
if (*ImageInfoSize < (sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR))) {
*ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
- DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImageInfo() - ImageInfoSize is to small.\n"));
+ DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImageInfo() - ImageInfoSize is to small.\n", mImageIdName));
Status = EFI_BUFFER_TOO_SMALL;
goto cleanup;
}
@@ -431,7 +482,7 @@ GetTheImageInfo (
//
if ( (ImageInfo == NULL) || (DescriptorVersion == NULL) || (DescriptorCount == NULL) || (DescriptorSize == NULL)
|| (PackageVersion == NULL)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImageInfo() - Pointer Parameter is NULL.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImageInfo() - Pointer Parameter is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
@@ -441,15 +492,15 @@ GetTheImageInfo (
//
*ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
-
- if (!mDescriptorPopulated) {
- PopulateDescriptor();
- }
+ //
+ // Make sure the descriptor has already been loaded or refreshed
+ //
+ PopulateDescriptor (Private);
//
// Copy the image descriptor
//
- CopyMem (ImageInfo, &mDesc, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));
+ CopyMem (ImageInfo, &Private->Descriptor, sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR));
*DescriptorVersion = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION;
*DescriptorCount = 1;
@@ -500,22 +551,33 @@ GetTheImage (
IN OUT UINTN *ImageSize
)
{
- EFI_STATUS Status;
- UINTN Size;
+ EFI_STATUS Status;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
+ UINTN Size;
+
+ if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
+ return EFI_UNSUPPORTED;
+ }
Status = EFI_SUCCESS;
+ //
+ // Retrieve the private context structure
+ //
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
+
//
// Check to make sure index is 1 (only 1 image for this device)
//
if (ImageIndex != 1) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Index Invalid.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Index Invalid.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
if (ImageSize == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - ImageSize Pointer Parameter is NULL.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - ImageSize Pointer Parameter is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
@@ -529,13 +591,13 @@ GetTheImage (
}
if (*ImageSize < Size) {
*ImageSize = Size;
- DEBUG ((DEBUG_VERBOSE, "FmpDxe: GetImage() - ImageSize is to small.\n"));
+ DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): GetImage() - ImageSize is to small.\n", mImageIdName));
Status = EFI_BUFFER_TOO_SMALL;
goto cleanup;
}
if (Image == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: GetImage() - Image Pointer Parameter is NULL.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): GetImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
@@ -550,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.
@@ -562,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);
}
/**
@@ -649,18 +713,21 @@ CheckTheImage (
OUT UINT32 *ImageUpdatable
)
{
- EFI_STATUS Status;
- UINTN RawSize;
- VOID *FmpPayloadHeader;
- UINTN FmpPayloadSize;
- UINT32 Version;
- UINT32 FmpHeaderSize;
- UINTN AllHeaderSize;
- UINT32 Index;
- VOID *PublicKeyData;
- UINTN PublicKeyDataLength;
- UINT8 *PublicKeyDataXdr;
- UINT8 *PublicKeyDataXdrEnd;
+ EFI_STATUS Status;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
+ UINTN RawSize;
+ VOID *FmpPayloadHeader;
+ UINTN FmpPayloadSize;
+ UINT32 Version;
+ UINT32 FmpHeaderSize;
+ UINTN AllHeaderSize;
+ UINT32 Index;
+ VOID *PublicKeyData;
+ UINTN PublicKeyDataLength;
+ UINT8 *PublicKeyDataXdr;
+ UINT8 *PublicKeyDataXdrEnd;
+ EFI_FIRMWARE_IMAGE_DEP *Dependencies;
+ UINT32 DependenciesSize;
Status = EFI_SUCCESS;
RawSize = 0;
@@ -669,16 +736,26 @@ CheckTheImage (
Version = 0;
FmpHeaderSize = 0;
AllHeaderSize = 0;
+ Dependencies = NULL;
+ DependenciesSize = 0;
+
+ if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
+ return EFI_UNSUPPORTED;
+ }
//
- // make sure the descriptor has already been loaded
+ // Retrieve the private context structure
//
- if (!mDescriptorPopulated) {
- PopulateDescriptor();
- }
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
+
+ //
+ // Make sure the descriptor has already been loaded or refreshed
+ //
+ PopulateDescriptor (Private);
if (ImageUpdatable == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
@@ -688,8 +765,13 @@ 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: CheckImage() - Image Pointer Parameter is NULL.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Pointer Parameter is NULL.\n", mImageIdName));
//
// not sure if this is needed
//
@@ -701,7 +783,7 @@ CheckTheImage (
PublicKeyDataXdrEnd = PublicKeyDataXdr + PcdGetSize (PcdFmpDevicePkcs7CertBufferXdr);
if (PublicKeyDataXdr == NULL || (PublicKeyDataXdr == PublicKeyDataXdrEnd)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Invalid certificate, skipping it.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Invalid certificate, skipping it.\n", mImageIdName));
Status = EFI_ABORTED;
} else {
//
@@ -711,7 +793,8 @@ CheckTheImage (
Index++;
DEBUG (
(DEBUG_INFO,
- "FmpDxe: Certificate #%d [%p..%p].\n",
+ "FmpDxe(%s): Certificate #%d [%p..%p].\n",
+ mImageIdName,
Index,
PublicKeyDataXdr,
PublicKeyDataXdrEnd
@@ -722,7 +805,7 @@ CheckTheImage (
//
// Key data extends beyond end of PCD
//
- DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate size extends beyond end of PCD, skipping it.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate size extends beyond end of PCD, skipping it.\n", mImageIdName));
Status = EFI_ABORTED;
break;
}
@@ -738,7 +821,7 @@ CheckTheImage (
//
// Key data extends beyond end of PCD
//
- DEBUG ((DEBUG_ERROR, "FmpDxe: Certificate extends beyond end of PCD, skipping it.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Certificate extends beyond end of PCD, skipping it.\n", mImageIdName));
Status = EFI_ABORTED;
break;
}
@@ -758,7 +841,7 @@ CheckTheImage (
}
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - Authentication Failed %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - Authentication Failed %r.\n", mImageIdName, Status));
goto cleanup;
}
@@ -766,25 +849,29 @@ CheckTheImage (
// Check to make sure index is 1
//
if (ImageIndex != 1) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - Image Index Invalid.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckImage() - Image Index Invalid.\n", mImageIdName));
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_TYPE;
Status = EFI_SUCCESS;
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: CheckTheImage() - GetFmpHeader failed.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpHeader failed.\n", mImageIdName));
Status = EFI_ABORTED;
goto cleanup;
}
Status = GetFmpPayloadHeaderVersion (FmpPayloadHeader, FmpPayloadSize, &Version);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetFmpPayloadHeaderVersion failed %r.\n", mImageIdName, Status));
*ImageUpdatable = IMAGE_UPDATABLE_INVALID;
Status = EFI_SUCCESS;
goto cleanup;
@@ -793,17 +880,28 @@ CheckTheImage (
//
// Check the lowest supported version
//
- if (Version < mDesc.LowestSupportedImageVersion) {
+ if (Version < Private->Descriptor.LowestSupportedImageVersion) {
DEBUG (
(DEBUG_ERROR,
- "FmpDxe: CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
- Version, mDesc.LowestSupportedImageVersion)
+ "FmpDxe(%s): CheckTheImage() - Version Lower than lowest supported version. 0x%08X < 0x%08X\n",
+ mImageIdName, Version, Private->Descriptor.LowestSupportedImageVersion)
);
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;
Status = EFI_SUCCESS;
goto cleanup;
}
+ //
+ // Evaluate dependency expression
+ //
+ 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;
+ }
+
//
// Get the FmpHeaderSize so we can determine the real payload size
//
@@ -819,9 +917,9 @@ CheckTheImage (
// Call FmpDevice Lib Check Image on the
// Raw payload. So all headers need stripped off
//
- AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );
+ AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
if (AllHeaderSize == 0) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - GetAllHeaderSize failed.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
Status = EFI_ABORTED;
goto cleanup;
}
@@ -832,7 +930,7 @@ CheckTheImage (
//
Status = FmpDeviceCheckImage ((((UINT8 *)Image) + AllHeaderSize), RawSize, ImageUpdatable);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): CheckTheImage() - FmpDeviceLib CheckImage failed. Status = %r\n", mImageIdName, Status));
}
cleanup:
@@ -897,17 +995,20 @@ SetTheImage (
OUT CHAR16 **AbortReason
)
{
- EFI_STATUS Status;
- UINT32 Updateable;
- BOOLEAN BooleanValue;
- UINT32 FmpHeaderSize;
- VOID *FmpHeader;
- UINTN FmpPayloadSize;
- UINT32 AllHeaderSize;
- UINT32 IncommingFwVersion;
- UINT32 LastAttemptStatus;
- UINT32 Version;
- UINT32 LowestSupportedVersion;
+ EFI_STATUS Status;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
+ UINT32 Updateable;
+ BOOLEAN BooleanValue;
+ UINT32 FmpHeaderSize;
+ VOID *FmpHeader;
+ UINTN FmpPayloadSize;
+ UINT32 AllHeaderSize;
+ UINT32 IncomingFwVersion;
+ UINT32 LastAttemptStatus;
+ UINT32 Version;
+ UINT32 LowestSupportedVersion;
+ EFI_FIRMWARE_IMAGE_DEP *Dependencies;
+ UINT32 DependenciesSize;
Status = EFI_SUCCESS;
Updateable = 0;
@@ -916,18 +1017,37 @@ SetTheImage (
FmpHeader = NULL;
FmpPayloadSize = 0;
AllHeaderSize = 0;
- IncommingFwVersion = 0;
+ IncomingFwVersion = 0;
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ Dependencies = NULL;
+ DependenciesSize = 0;
+
+ if (!FeaturePcdGet (PcdFmpDeviceStorageAccessEnable)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Retrieve the private context structure
+ //
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
+ //
+ // Make sure the descriptor has already been loaded or refreshed
+ //
+ PopulateDescriptor (Private);
- SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.
+ //
+ // Set to 0 to clear any previous results.
+ //
+ SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
//
// if we have locked the device, then skip the set operation.
// it should be blocked by hardware too but we can catch here even faster
//
- if (mFmpDeviceLocked) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Device is already locked. Can't update.\n"));
+ if (Private->FmpDeviceLocked) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Device is already locked. Can't update.\n", mImageIdName));
Status = EFI_UNSUPPORTED;
goto cleanup;
}
@@ -937,57 +1057,64 @@ SetTheImage (
//
Status = CheckTheImage (This, ImageIndex, Image, ImageSize, &Updateable);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Check The Image failed with %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Check The Image failed with %r.\n", mImageIdName, Status));
if (Status == EFI_SECURITY_VIOLATION) {
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_AUTH_ERROR;
}
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: SetTheImage() - GetFmpHeader failed.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpHeader failed.\n", mImageIdName));
Status = EFI_ABORTED;
goto cleanup;
}
- Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncommingFwVersion);
+ Status = GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &IncomingFwVersion);
if (!EFI_ERROR (Status)) {
//
// Set to actual value
//
- SetLastAttemptVersionInVariable (IncommingFwVersion);
+ SetLastAttemptVersionInVariable (Private, IncomingFwVersion);
}
if (Updateable != IMAGE_UPDATABLE_VALID) {
DEBUG (
(DEBUG_ERROR,
- "FmpDxed: SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
- Updateable)
+ "FmpDxe(%s): SetTheImage() - Check The Image returned that the Image was not valid for update. Updatable value = 0x%X.\n",
+ mImageIdName, Updateable)
);
+ if (Private->DependenciesSatisfied == FALSE) {
+ LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSATISFIED_DEPENDENCIES;
+ }
Status = EFI_ABORTED;
goto cleanup;
}
if (Progress == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Invalid progress callback\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Invalid progress callback\n", mImageIdName));
Status = EFI_INVALID_PARAMETER;
goto cleanup;
}
mProgressFunc = Progress;
- mProgressSupported = TRUE;
//
// Checking the image is at least 1%
//
Status = Progress (1);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Progress Callback failed with Status %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - Progress Callback failed with Status %r.\n", mImageIdName, Status));
}
//
@@ -995,14 +1122,14 @@ SetTheImage (
//
Status = CheckSystemPower (&BooleanValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemPower - API call failed %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemPower - API call failed %r.\n", mImageIdName, Status));
goto cleanup;
}
if (!BooleanValue) {
Status = EFI_ABORTED;
DEBUG (
(DEBUG_ERROR,
- "FmpDxe: SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n")
+ "FmpDxe(%s): SetTheImage() - CheckSystemPower - returned False. Update not allowed due to System Power.\n", mImageIdName)
);
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_PWR_EVT_BATT;
goto cleanup;
@@ -1015,14 +1142,14 @@ SetTheImage (
//
Status = CheckSystemThermal (&BooleanValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemThermal - API call failed %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemThermal - API call failed %r.\n", mImageIdName, Status));
goto cleanup;
}
if (!BooleanValue) {
Status = EFI_ABORTED;
DEBUG (
(DEBUG_ERROR,
- "FmpDxe: SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n")
+ "FmpDxe(%s): SetTheImage() - CheckSystemThermal - returned False. Update not allowed due to System Thermal.\n", mImageIdName)
);
goto cleanup;
}
@@ -1034,14 +1161,14 @@ SetTheImage (
//
Status = CheckSystemEnvironment (&BooleanValue);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - API call failed %r.\n", mImageIdName, Status));
goto cleanup;
}
if (!BooleanValue) {
Status = EFI_ABORTED;
DEBUG (
(DEBUG_ERROR,
- "FmpDxe: SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n")
+ "FmpDxe(%s): SetTheImage() - CheckSystemEnvironment - returned False. Update not allowed due to System Environment.\n", mImageIdName)
);
goto cleanup;
}
@@ -1052,20 +1179,20 @@ SetTheImage (
// Save LastAttemptStatus as error so that if SetImage never returns the error
// state is recorded.
//
- SetLastAttemptStatusInVariable (LastAttemptStatus);
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
//
// Strip off all the headers so the device can process its firmware
//
Status = GetFmpPayloadHeaderSize (FmpHeader, FmpPayloadSize, &FmpHeaderSize);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetFmpPayloadHeaderSize failed %r.\n", mImageIdName, Status));
goto cleanup;
}
- AllHeaderSize = GetAllHeaderSize ( (EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize );
+ AllHeaderSize = GetAllHeaderSize ((EFI_FIRMWARE_IMAGE_AUTHENTICATION *)Image, FmpHeaderSize + DependenciesSize);
if (AllHeaderSize == 0) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - GetAllHeaderSize failed.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() - GetAllHeaderSize failed.\n", mImageIdName));
Status = EFI_ABORTED;
goto cleanup;
}
@@ -1083,14 +1210,24 @@ SetTheImage (
ImageSize - AllHeaderSize,
VendorCode,
FmpDxeProgress,
- IncommingFwVersion,
+ IncomingFwVersion,
AbortReason
);
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): SetTheImage() SetImage from FmpDeviceLib failed. Status = %r.\n", mImageIdName, Status));
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
@@ -1101,27 +1238,24 @@ SetTheImage (
//
// Update the version stored in variable
//
- if (!mRuntimeVersionSupported) {
+ if (!Private->RuntimeVersionSupported) {
Version = DEFAULT_VERSION;
GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
- SetVersionInVariable (Version);
+ SetVersionInVariable (Private, Version);
}
//
// Update lowest supported variable
//
- {
- LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
- GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
- SetLowestSupportedVersionInVariable (LowestSupportedVersion);
- }
+ LowestSupportedVersion = DEFAULT_LOWESTSUPPORTEDVERSION;
+ GetFmpPayloadHeaderLowestSupportedVersion (FmpHeader, FmpPayloadSize, &LowestSupportedVersion);
+ SetLowestSupportedVersionInVariable (Private, LowestSupportedVersion);
LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;
cleanup:
mProgressFunc = NULL;
- mProgressSupported = FALSE;
- SetLastAttemptStatusInVariable (LastAttemptStatus);
+ SetLastAttemptStatusInVariable (Private, LastAttemptStatus);
if (Progress != NULL) {
//
@@ -1134,7 +1268,7 @@ cleanup:
// Need repopulate after SetImage is called to
// update LastAttemptVersion and LastAttemptStatus.
//
- mDescriptorPopulated = FALSE;
+ Private->DescriptorPopulated = FALSE;
return Status;
}
@@ -1245,35 +1379,25 @@ FmpDxeLockEventNotify (
IN VOID *Context
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- if (!mFmpDeviceLocked) {
- if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
- //
- // Lock all UEFI Variables used by this module.
- //
- Status = LockAllFmpVariables ();
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to lock variables. Status = %r.\n"));
- } else {
- DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));
- }
+ Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;
- //
- // Lock the firmware device
- //
- Status = FmpDeviceLock();
- if (EFI_ERROR (Status)) {
- if (Status != EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));
- } else {
- DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));
- }
+ if (!Private->FmpDeviceLocked) {
+ //
+ // Lock the firmware device
+ //
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
+ Status = FmpDeviceLock();
+ if (EFI_ERROR (Status)) {
+ if (Status != EFI_UNSUPPORTED) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));
+ } else {
+ DEBUG ((DEBUG_WARN, "FmpDxe(%s): FmpDeviceLock() returned error. Status = %r\n", mImageIdName, Status));
}
- mFmpDeviceLocked = TRUE;
- } else {
- DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not calling FmpDeviceLock() because mfg mode\n"));
}
+ Private->FmpDeviceLocked = TRUE;
}
}
@@ -1293,85 +1417,233 @@ InstallFmpInstance (
IN EFI_HANDLE Handle
)
{
- EFI_STATUS Status;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *FmpProgress;
-
- Status = EFI_SUCCESS;
- Fmp = NULL;
- FmpProgress = NULL;
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
//
// Only allow a single FMP Protocol instance to be installed
//
- if (mFmpInstalled) {
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **)&Fmp,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
//
// Allocate FMP Protocol instance
//
- Fmp = AllocateZeroPool (sizeof (EFI_FIRMWARE_MANAGEMENT_PROTOCOL));
- if (Fmp == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Protocol instance.\n"));
+ Private = AllocateCopyPool (
+ sizeof (mFirmwareManagementPrivateDataTemplate),
+ &mFirmwareManagementPrivateDataTemplate
+ );
+ if (Private == NULL) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to allocate memory for private structure.\n", mImageIdName));
Status = EFI_OUT_OF_RESOURCES;
goto cleanup;
}
//
- // Allocate FMP Progress Protocol instance
+ // Initialize private context data structure
//
- FmpProgress = AllocateZeroPool (sizeof (EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL));
- if (FmpProgress == NULL) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to allocate memory for FMP Progress Protocol instance.\n"));
- Status = EFI_OUT_OF_RESOURCES;
- FreePool (Fmp);
+ Private->Handle = Handle;
+ Private->FmpDeviceContext = NULL;
+ Status = FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
+ if (Status == EFI_UNSUPPORTED) {
+ Private->FmpDeviceContext = NULL;
+ } else if (EFI_ERROR (Status)) {
goto cleanup;
}
//
- // Set up FMP Protocol function pointers
+ // Make sure the descriptor has already been loaded or refreshed
//
- Fmp->GetImageInfo = GetTheImageInfo;
- Fmp->GetImage = GetTheImage;
- Fmp->SetImage = SetTheImage;
- Fmp->CheckImage = CheckTheImage;
- Fmp->GetPackageInfo = GetPackageInfo;
- Fmp->SetPackageInfo = SetPackageInfo;
+ PopulateDescriptor (Private);
- //
- // Fill in FMP Progress Protocol fields for Version 1
- //
- FmpProgress->Version = 1;
- FmpProgress->ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
- FmpProgress->WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
+ if (IsLockFmpDeviceAtLockEventGuidRequired ()) {
+ //
+ // Register all UEFI Variables used by this module to be locked.
+ //
+ Status = LockAllFmpVariables (Private);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register variables to lock. Status = %r.\n", mImageIdName, Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): All variables registered to lock\n", mImageIdName));
+ }
+
+ //
+ // Create and register notify function to lock the FMP device.
+ //
+ Status = gBS->CreateEventEx (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ FmpDxeLockEventNotify,
+ Private,
+ mLockGuid,
+ &Private->FmpDeviceLockEvent
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Failed to register notification. Status = %r\n", mImageIdName, Status));
+ }
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((DEBUG_VERBOSE, "FmpDxe(%s): Not registering notification to call FmpDeviceLock() because mfg mode\n", mImageIdName));
+ }
//
// Install FMP Protocol and FMP Progress Protocol
//
Status = gBS->InstallMultipleProtocolInterfaces (
- &Handle,
- &gEfiFirmwareManagementProtocolGuid,
- Fmp,
- &gEdkiiFirmwareManagementProgressProtocolGuid,
- FmpProgress,
+ &Private->Handle,
+ &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,
+ &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,
NULL
);
-
if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: FMP Protocol install error. Status = %r.\n", Status));
- FreePool (Fmp);
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol install error. Status = %r.\n", mImageIdName, Status));
goto cleanup;
}
- DEBUG ((DEBUG_INFO, "FmpDxe: FMP Protocol Installed!\n"));
- mFmpInstalled = TRUE;
-
cleanup:
+ if (EFI_ERROR (Status)) {
+ if (Private != NULL) {
+ if (Private->FmpDeviceLockEvent != NULL) {
+ gBS->CloseEvent (Private->FmpDeviceLockEvent);
+ }
+ if (Private->Descriptor.VersionName != NULL) {
+ FreePool (Private->Descriptor.VersionName);
+ }
+ if (Private->FmpDeviceContext != NULL) {
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
+ }
+ if (Private->VersionVariableName != NULL) {
+ FreePool (Private->VersionVariableName);
+ }
+ if (Private->LsvVariableName != NULL) {
+ FreePool (Private->LsvVariableName);
+ }
+ if (Private->LastAttemptStatusVariableName != NULL) {
+ FreePool (Private->LastAttemptStatusVariableName);
+ }
+ if (Private->LastAttemptVersionVariableName != NULL) {
+ FreePool (Private->LastAttemptVersionVariableName);
+ }
+ if (Private->FmpStateVariableName != NULL) {
+ FreePool (Private->FmpStateVariableName);
+ }
+ FreePool (Private);
+ }
+ }
+
return Status;
}
+/**
+ Function to uninstall FMP instance.
+
+ @param[in] Handle The device handle to install a FMP instance on.
+
+ @retval EFI_SUCCESS FMP Installed
+ @retval EFI_INVALID_PARAMETER Handle was invalid
+ @retval other Error installing FMP
+
+**/
+EFI_STATUS
+EFIAPI
+UninstallFmpInstance (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
+
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **)&Fmp,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol open error. Status = %r.\n", mImageIdName, Status));
+ return Status;
+ }
+
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (Fmp);
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
+
+ if (Private->FmpDeviceLockEvent != NULL) {
+ gBS->CloseEvent (Private->FmpDeviceLockEvent);
+ }
+
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ Private->Handle,
+ &gEfiFirmwareManagementProtocolGuid, &Private->Fmp,
+ &gEdkiiFirmwareManagementProgressProtocolGuid, &mFmpProgress,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): Protocol uninstall error. Status = %r.\n", mImageIdName, Status));
+ return Status;
+ }
+
+ if (Private->Descriptor.VersionName != NULL) {
+ FreePool (Private->Descriptor.VersionName);
+ }
+ if (Private->FmpDeviceContext != NULL) {
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
+ }
+ if (Private->VersionVariableName != NULL) {
+ FreePool (Private->VersionVariableName);
+ }
+ if (Private->LsvVariableName != NULL) {
+ FreePool (Private->LsvVariableName);
+ }
+ if (Private->LastAttemptStatusVariableName != NULL) {
+ FreePool (Private->LastAttemptStatusVariableName);
+ }
+ if (Private->LastAttemptVersionVariableName != NULL) {
+ FreePool (Private->LastAttemptVersionVariableName);
+ }
+ if (Private->FmpStateVariableName != NULL) {
+ FreePool (Private->FmpStateVariableName);
+ }
+ FreePool (Private);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Unloads the application and its installed protocol.
+
+ @param ImageHandle Handle that identifies the image to be unloaded.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+EFIAPI
+FmpDxeLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (mFmpSingleInstance) {
+ return UninstallFmpInstance (ImageHandle);
+ }
+ return EFI_SUCCESS;
+}
+
/**
Main entry for this driver/library.
@@ -1387,7 +1659,6 @@ FmpDxeEntryPoint (
)
{
EFI_STATUS Status;
- EFI_GUID *LockGuid;
//
// Verify that a new FILE_GUID value has been provided in the
@@ -1408,8 +1679,9 @@ FmpDxeEntryPoint (
//
// PcdFmpDeviceImageIdName must be set to a non-empty Unicode string
//
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib PcdFmpDeviceImageIdName is an empty string.\n"));
+ DEBUG ((DEBUG_ERROR, "FmpDxe: PcdFmpDeviceImageIdName is an empty string.\n"));
ASSERT (FALSE);
+ return EFI_UNSUPPORTED;
}
//
@@ -1417,6 +1689,23 @@ FmpDxeEntryPoint (
//
DetectTestKey ();
+ //
+ // Fill in FMP Progress Protocol fields for Version 1
+ //
+ mFmpProgress.Version = 1;
+ mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
+ mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
+
+ // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
+ // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
+ // gEfiEndOfDxeEventGroupGuid is used.
+ //
+ mLockGuid = &gEfiEndOfDxeEventGroupGuid;
+ if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {
+ mLockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);
+ }
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): Lock GUID: %g\n", mImageIdName, mLockGuid));
+
//
// Register with library the install function so if the library uses
// UEFI driver model/driver binding protocol it can install FMP on its device handle
@@ -1425,41 +1714,28 @@ FmpDxeEntryPoint (
//
Status = RegisterFmpInstaller (InstallFmpInstance);
if (Status == EFI_UNSUPPORTED) {
- DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n"));
- Status = InstallFmpInstance (ImageHandle);
+ mFmpSingleInstance = TRUE;
+ DEBUG ((DEBUG_INFO, "FmpDxe(%s): FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n", mImageIdName));
+ Status = RegisterFmpUninstaller (UninstallFmpInstance);
+ if (Status == EFI_UNSUPPORTED) {
+ Status = InstallFmpInstance (ImageHandle);
+ } else {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
+ Status = EFI_UNSUPPORTED;
+ }
} else if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib registration returned %r. No FMP installed.\n", Status));
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib registration returned %r. No FMP installed.\n", mImageIdName, Status));
} else {
DEBUG ((
DEBUG_INFO,
- "FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n"
+ "FmpDxe(%s): FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n",
+ mImageIdName
));
+ Status = RegisterFmpUninstaller (UninstallFmpInstance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe(%s): FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n", mImageIdName));
+ }
}
- //
- // Register notify function to lock the FMP device.
- // The lock event GUID is retrieved from PcdFmpDeviceLockEventGuid.
- // If PcdFmpDeviceLockEventGuid is not the size of an EFI_GUID, then
- // gEfiEndOfDxeEventGroupGuid is used.
- //
- LockGuid = &gEfiEndOfDxeEventGroupGuid;
- if (PcdGetSize (PcdFmpDeviceLockEventGuid) == sizeof (EFI_GUID)) {
- LockGuid = (EFI_GUID *)PcdGetPtr (PcdFmpDeviceLockEventGuid);
- }
- DEBUG ((DEBUG_INFO, "FmpDxe: Lock GUID: %g\n", LockGuid));
-
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- FmpDxeLockEventNotify,
- NULL,
- LockGuid,
- &mFmpDeviceLockEvent
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register for ready to boot. Status = %r\n", Status));
- }
- ASSERT_EFI_ERROR (Status);
-
return Status;
}