summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Jin <eric.jin@intel.com>2019-08-11 11:38:13 +0800
committerLiming Gao <liming.gao@intel.com>2019-08-15 17:22:23 +0800
commit4f0544b144b953ed4e8b4221fc33353f4481ec14 (patch)
tree9ae8df8c071695de9e60603a59b39b899df1561f
parenta6ee24fbddcd901347014e045611eb6108f4f741 (diff)
downloadedk2-4f0544b144b953ed4e8b4221fc33353f4481ec14.tar.gz
edk2-4f0544b144b953ed4e8b4221fc33353f4481ec14.tar.bz2
edk2-4f0544b144b953ed4e8b4221fc33353f4481ec14.zip
FmpDevicePkg/FmpDxe: Use new FmpDeviceLib APIs
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=1525 Update FmpDxe to support multiple controllers and use new FmpDeviceLib APIs to support Stop/Unload and to set the context for the worker functions in the FmpDeviceLib. Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com> Cc: Liming Gao <liming.gao@intel.com> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Eric Jin <eric.jin@intel.com> Reviewed-by: Liming Gao <liming.gao@intel.com>
-rw-r--r--FmpDevicePkg/FmpDxe/FmpDxe.c586
-rw-r--r--FmpDevicePkg/FmpDxe/FmpDxe.h341
-rw-r--r--FmpDevicePkg/FmpDxe/FmpDxe.inf4
-rw-r--r--FmpDevicePkg/FmpDxe/FmpDxeLib.inf4
4 files changed, 715 insertions, 220 deletions
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.c b/FmpDevicePkg/FmpDxe/FmpDxe.c
index f485f5b939..dab3310834 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.c
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.c
@@ -4,46 +4,13 @@
information provided through PCDs and libraries.
Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
- Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
-#include <PiDxe.h>
-#include <Library/DebugLib.h>
-#include <Library/BaseLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/UefiLib.h>
-#include <Library/FmpAuthenticationLib.h>
-#include <Library/FmpDeviceLib.h>
-#include <Library/FmpPayloadHeaderLib.h>
-#include <Library/CapsuleUpdatePolicyLib.h>
-#include <Protocol/FirmwareManagement.h>
-#include <Protocol/FirmwareManagementProgress.h>
-#include <Guid/SystemResourceTable.h>
-#include <Guid/EventGroup.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
- );
+#include "FmpDxe.h"
///
/// FILE_GUID from FmpDxe.inf. When FmpDxe.inf is used in a platform, the
@@ -56,30 +23,73 @@ 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
+};
+
+///
+/// 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.
@@ -111,10 +121,6 @@ FmpDxeProgress (
Status = EFI_UNSUPPORTED;
- if (!mProgressSupported) {
- return Status;
- }
-
if (mProgressFunc == NULL) {
return Status;
}
@@ -125,7 +131,6 @@ FmpDxeProgress (
Status = mProgressFunc (((Completion * 92) / 100) + 6);
if (Status == EFI_UNSUPPORTED) {
- mProgressSupported = FALSE;
mProgressFunc = NULL;
}
@@ -183,7 +188,7 @@ 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
+ @return The largest value
**/
UINT32
@@ -237,101 +242,117 @@ 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;
- 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 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();
} 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;
+ 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
- );
+ 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
- );
+ Private->Descriptor.VersionName = AllocateCopyPool (
+ sizeof (VERSION_STRING_NOT_AVAILABLE),
+ VERSION_STRING_NOT_AVAILABLE
+ );
}
- mDesc.VersionName = mVersionName;
-
- mDesc.LowestSupportedImageVersion = GetLowestSupportedVersion();
+ Private->Descriptor.LowestSupportedImageVersion = GetLowestSupportedVersion();
//
// 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->Descriptor.LastAttemptStatus = GetLastAttemptStatusFromVariable ();
- mDescriptorPopulated = TRUE;
+ //
+ // Get the hardware instance from FmpDeviceLib
+ //
+ Status = FmpDeviceGetHardwareInstance (&Private->Descriptor.HardwareInstance);
+ if (Status == EFI_UNSUPPORTED) {
+ Private->Descriptor.HardwareInstance = 0;
+ }
+
+ Private->DescriptorPopulated = TRUE;
}
/**
@@ -385,11 +406,18 @@ 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) {
@@ -424,15 +452,15 @@ GetTheImageInfo (
//
*ImageInfoSize = sizeof (EFI_FIRMWARE_IMAGE_DESCRIPTOR);
-
- if (!mDescriptorPopulated) {
- PopulateDescriptor();
- }
+ //
+ // make sure the descriptor has already been loaded
+ //
+ 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;
@@ -483,12 +511,19 @@ GetTheImage (
IN OUT UINTN *ImageSize
)
{
- EFI_STATUS Status;
- UINTN Size;
+ EFI_STATUS Status;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
+ UINTN Size;
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) {
@@ -632,18 +667,19 @@ 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;
Status = EFI_SUCCESS;
RawSize = 0;
@@ -654,11 +690,15 @@ CheckTheImage (
AllHeaderSize = 0;
//
+ // 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
//
- if (!mDescriptorPopulated) {
- PopulateDescriptor();
- }
+ PopulateDescriptor (Private);
if (ImageUpdatable == NULL) {
DEBUG ((DEBUG_ERROR, "FmpDxe: CheckImage() - ImageUpdatable Pointer Parameter is NULL.\n"));
@@ -776,11 +816,11 @@ 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)
+ Version, Private->Descriptor.LowestSupportedImageVersion)
);
*ImageUpdatable = IMAGE_UPDATABLE_INVALID_OLD;
Status = EFI_SUCCESS;
@@ -880,17 +920,18 @@ 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 IncommingFwVersion;
+ UINT32 LastAttemptStatus;
+ UINT32 Version;
+ UINT32 LowestSupportedVersion;
Status = EFI_SUCCESS;
Updateable = 0;
@@ -902,6 +943,11 @@ SetTheImage (
IncommingFwVersion = 0;
LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;
+ //
+ // Retrieve the private context structure
+ //
+ Private = FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS (This);
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
SetLastAttemptVersionInVariable (IncommingFwVersion); //set to 0 to clear any previous results.
@@ -909,7 +955,7 @@ SetTheImage (
// 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) {
+ if (Private->FmpDeviceLocked) {
DEBUG ((DEBUG_ERROR, "FmpDxe: SetTheImage() - Device is already locked. Can't update.\n"));
Status = EFI_UNSUPPORTED;
goto cleanup;
@@ -963,7 +1009,6 @@ SetTheImage (
}
mProgressFunc = Progress;
- mProgressSupported = TRUE;
//
// Checking the image is at least 1%
@@ -1084,7 +1129,7 @@ SetTheImage (
//
// Update the version stored in variable
//
- if (!mRuntimeVersionSupported) {
+ if (!Private->RuntimeVersionSupported) {
Version = DEFAULT_VERSION;
GetFmpPayloadHeaderVersion (FmpHeader, FmpPayloadSize, &Version);
SetVersionInVariable (Version);
@@ -1103,7 +1148,6 @@ SetTheImage (
cleanup:
mProgressFunc = NULL;
- mProgressSupported = FALSE;
SetLastAttemptStatusInVariable (LastAttemptStatus);
if (Progress != NULL) {
@@ -1117,7 +1161,7 @@ cleanup:
// Need repopulate after SetImage is called to
// update LastAttemptVersion and LastAttemptStatus.
//
- mDescriptorPopulated = FALSE;
+ Private->DescriptorPopulated = FALSE;
return Status;
}
@@ -1228,12 +1272,16 @@ FmpDxeLockEventNotify (
IN VOID *Context
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
+
+ Private = (FIRMWARE_MANAGEMENT_PRIVATE_DATA *)Context;
- if (!mFmpDeviceLocked) {
+ if (!Private->FmpDeviceLocked) {
//
// Lock the firmware device
//
+ FmpDeviceSetContext (Private->Handle, &Private->FmpDeviceContext);
Status = FmpDeviceLock();
if (EFI_ERROR (Status)) {
if (Status != EFI_UNSUPPORTED) {
@@ -1242,7 +1290,7 @@ FmpDxeLockEventNotify (
DEBUG ((DEBUG_WARN, "FmpDxe: FmpDeviceLock() returned error. Status = %r\n", Status));
}
}
- mFmpDeviceLocked = TRUE;
+ Private->FmpDeviceLocked = TRUE;
}
}
@@ -1262,86 +1310,199 @@ InstallFmpInstance (
IN EFI_HANDLE Handle
)
{
- EFI_STATUS Status;
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
- EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *FmpProgress;
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;
+ FIRMWARE_MANAGEMENT_PRIVATE_DATA *Private;
- Status = EFI_SUCCESS;
- Fmp = NULL;
- FmpProgress = NULL;
+ DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Entry\n"));
//
// 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: Failed to allocate memory for private structure.\n"));
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);
+ DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Initialize private context data structure\n"));
+
+ 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
- //
- Fmp->GetImageInfo = GetTheImageInfo;
- Fmp->GetImage = GetTheImage;
- Fmp->SetImage = SetTheImage;
- Fmp->CheckImage = CheckTheImage;
- Fmp->GetPackageInfo = GetPackageInfo;
- Fmp->SetPackageInfo = SetPackageInfo;
+ DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Lock events\n"));
- //
- // Fill in FMP Progress Protocol fields for Version 1
- //
- FmpProgress->Version = 1;
- FmpProgress->ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
- FmpProgress->WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
+ 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", Status));
+ } else {
+ DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));
+ }
+
+ //
+ // 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: Failed to register notification. Status = %r\n", Status));
+ }
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not registering notification to call FmpDeviceLock() because mfg mode\n"));
+ }
//
// Install FMP Protocol and FMP Progress Protocol
//
+ DEBUG ((DEBUG_ERROR, "InstallFmpInstance: Install FMP Protocol and FMP Progress Protocol\n"));
+
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: Protocol install error. Status = %r.\n", Status));
goto cleanup;
}
- DEBUG ((DEBUG_INFO, "FmpDxe: FMP Protocol Installed!\n"));
- mFmpInstalled = TRUE;
+ DEBUG ((DEBUG_INFO, "FmpDxe: Protocols Installed!\n"));
cleanup:
+ if (EFI_ERROR (Status)) {
+ if (Private != NULL) {
+ if (Private->FmpDeviceLockEvent != NULL) {
+ gBS->CloseEvent (Private->FmpDeviceLockEvent);
+ }
+ 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)) {
+ 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)) {
+ return Status;
+ }
+
+ FmpDeviceSetContext (NULL, &Private->FmpDeviceContext);
+
+ 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.
@param[in] ImageHandle Image handle this driver.
@@ -1356,7 +1517,6 @@ FmpDxeEntryPoint (
)
{
EFI_STATUS Status;
- EFI_GUID *LockGuid;
//
// Verify that a new FILE_GUID value has been provided in the <Defines>
@@ -1381,49 +1541,28 @@ FmpDxeEntryPoint (
ASSERT (FALSE);
}
+
//
// Detects if PcdFmpDevicePkcs7CertBufferXdr contains a test key.
//
DetectTestKey ();
- 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", Status));
- } else {
- DEBUG ((DEBUG_INFO, "FmpDxe: All variables locked\n"));
- }
-
- //
- // 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));
+ //
+ // Fill in FMP Progress Protocol fields for Version 1
+ //
+ mFmpProgress.Version = 1;
+ mFmpProgress.ProgressBarForegroundColor.Raw = PcdGet32 (PcdFmpDeviceProgressColor);
+ mFmpProgress.WatchdogSeconds = PcdGet8 (PcdFmpDeviceProgressWatchdogTimeInSeconds);
- Status = gBS->CreateEventEx (
- EVT_NOTIFY_SIGNAL,
- TPL_CALLBACK,
- FmpDxeLockEventNotify,
- NULL,
- LockGuid,
- &mFmpDeviceLockEvent
- );
- if (EFI_ERROR (Status)) {
- DEBUG ((DEBUG_ERROR, "FmpDxe: Failed to register notification. Status = %r\n", Status));
- }
- ASSERT_EFI_ERROR (Status);
- } else {
- DEBUG ((DEBUG_VERBOSE, "FmpDxe: Not registering notification to call FmpDeviceLock() because mfg mode\n"));
+ // 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: Lock GUID: %g\n", mLockGuid));
//
// Register with library the install function so if the library uses
@@ -1433,8 +1572,15 @@ FmpDxeEntryPoint (
//
Status = RegisterFmpInstaller (InstallFmpInstance);
if (Status == EFI_UNSUPPORTED) {
+ mFmpSingleInstance = TRUE;
DEBUG ((DEBUG_INFO, "FmpDxe: FmpDeviceLib registration returned EFI_UNSUPPORTED. Installing single FMP instance.\n"));
- Status = InstallFmpInstance (ImageHandle);
+ Status = RegisterFmpUninstaller (UninstallFmpInstance);
+ if (Status == EFI_UNSUPPORTED) {
+ Status = InstallFmpInstance (ImageHandle);
+ } else {
+ DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n"));
+ Status = EFI_UNSUPPORTED;
+ }
} else if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib registration returned %r. No FMP installed.\n", Status));
} else {
@@ -1442,6 +1588,10 @@ FmpDxeEntryPoint (
DEBUG_INFO,
"FmpDxe: FmpDeviceLib registration returned EFI_SUCCESS. Expect FMP to be installed during the BDS/Device connection phase.\n"
));
+ Status = RegisterFmpUninstaller (UninstallFmpInstance);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "FmpDxe: FmpDeviceLib RegisterFmpInstaller and RegisterFmpUninstaller do not match.\n"));
+ }
}
return Status;
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.h b/FmpDevicePkg/FmpDxe/FmpDxe.h
new file mode 100644
index 0000000000..c2ffc439d1
--- /dev/null
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.h
@@ -0,0 +1,341 @@
+/** @file
+ Produces a Firmware Management Protocol that supports updates to a firmware
+ image stored in a firmware device with platform and firmware device specific
+ information provided through PCDs and libraries.
+
+ Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
+ Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _FMP_DXE_H_
+#define _FMP_DXE_H_
+
+#include <PiDxe.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiLib.h>
+#include <Library/FmpAuthenticationLib.h>
+#include <Library/FmpDeviceLib.h>
+#include <Library/FmpPayloadHeaderLib.h>
+#include <Library/CapsuleUpdatePolicyLib.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/FirmwareManagementProgress.h>
+#include <Guid/SystemResourceTable.h>
+#include <Guid/EventGroup.h>
+#include "VariableSupport.h"
+
+#define VERSION_STRING_NOT_SUPPORTED L"VERSION STRING NOT SUPPORTED"
+#define VERSION_STRING_NOT_AVAILABLE L"VERSION STRING NOT AVAILABLE"
+
+///
+///
+///
+#define FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('f','m','p','p')
+
+typedef struct {
+ UINTN Signature;
+ EFI_HANDLE Handle;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL Fmp;
+ BOOLEAN DescriptorPopulated;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR Descriptor;
+ CHAR16 *ImageIdName;
+ CHAR16 *VersionName;
+ BOOLEAN RuntimeVersionSupported;
+ EFI_EVENT FmpDeviceLockEvent;
+ //
+ // 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.
+ //
+ BOOLEAN FmpDeviceLocked;
+ VOID *FmpDeviceContext;
+} FIRMWARE_MANAGEMENT_PRIVATE_DATA;
+
+///
+///
+///
+#define FIRMWARE_MANAGEMENT_PRIVATE_DATA_FROM_THIS(a) \
+ CR (a, FIRMWARE_MANAGEMENT_PRIVATE_DATA, Fmp, FIRMWARE_MANAGEMENT_PRIVATE_DATA_SIGNATURE)
+
+/**
+ 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
+ );
+
+/**
+ Returns information about the current firmware image(s) of the device.
+
+ This function allows a copy of the current firmware image to be created and saved.
+ The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in, out] ImageInfoSize A pointer to the size, in bytes, of the ImageInfo buffer.
+ On input, this is the size of the buffer allocated by the caller.
+ On output, it is the size of the buffer returned by the firmware
+ if the buffer was large enough, or the size of the buffer needed
+ to contain the image(s) information if the buffer was too small.
+ @param[in, out] ImageInfo A pointer to the buffer in which firmware places the current image(s)
+ information. The information is an array of EFI_FIRMWARE_IMAGE_DESCRIPTORs.
+ @param[out] DescriptorVersion A pointer to the location in which firmware returns the version number
+ associated with the EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] DescriptorCount A pointer to the location in which firmware returns the number of
+ descriptors or firmware images within this device.
+ @param[out] DescriptorSize A pointer to the location in which firmware returns the size, in bytes,
+ of an individual EFI_FIRMWARE_IMAGE_DESCRIPTOR.
+ @param[out] PackageVersion A version number that represents all the firmware images in the device.
+ The format is vendor specific and new version must have a greater value
+ than the old version. If PackageVersion is not supported, the value is
+ 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version comparison
+ is to be performed using PackageVersionName. A value of 0xFFFFFFFD indicates
+ that package version update is in progress.
+ @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing the
+ package version name. The buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility to free it with a call
+ to FreePool().
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_BUFFER_TOO_SMALL The ImageInfo buffer was too small. The current buffer size
+ needed to hold the image(s) information is returned in ImageInfoSize.
+ @retval EFI_INVALID_PARAMETER ImageInfoSize is NULL.
+ @retval EFI_DEVICE_ERROR Valid information could not be returned. Possible corrupted image.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTheImageInfo (
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN OUT UINTN *ImageInfoSize,
+ IN OUT EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo,
+ OUT UINT32 *DescriptorVersion,
+ OUT UINT8 *DescriptorCount,
+ OUT UINTN *DescriptorSize,
+ OUT UINT32 *PackageVersion,
+ OUT CHAR16 **PackageVersionName
+ );
+
+/**
+ Retrieves a copy of the current firmware image of the device.
+
+ This function allows a copy of the current firmware image to be created and saved.
+ The saved copy could later been used, for example, in firmware image recovery or rollback.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in, out] Image Points to the buffer where the current image is copied to.
+ @param[in, out] ImageSize On entry, points to the size of the buffer pointed to by Image, in bytes.
+ On return, points to the length of the image, in bytes.
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_BUFFER_TOO_SMALL The buffer specified by ImageSize is too small to hold the
+ image. The current buffer size needed to hold the image is returned
+ in ImageSize.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_NOT_FOUND The current image is not copied to the buffer.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+GetTheImage (
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN OUT VOID *Image,
+ IN OUT UINTN *ImageSize
+ );
+
+
+/**
+ Checks if the firmware image is valid for the device.
+
+ This function allows firmware update application to validate the firmware image without
+ invoking the SetImage() first.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in] Image Points to the new image.
+ @param[in] ImageSize Size of the new image in bytes.
+ @param[out] ImageUpdatable Indicates if the new image is valid for update. It also provides,
+ if available, additional information if the image is invalid.
+
+ @retval EFI_SUCCESS The image was successfully checked.
+ @retval EFI_ABORTED The operation is aborted.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+CheckTheImage (
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ OUT UINT32 *ImageUpdatable
+ );
+
+/**
+ Updates the firmware image of the device.
+
+ This function updates the hardware with the new firmware image.
+ This function returns EFI_UNSUPPORTED if the firmware image is not updatable.
+ If the firmware image is updatable, the function should perform the following minimal validations
+ before proceeding to do the firmware image update.
+ - Validate the image authentication if image has attribute
+ IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED. The function returns
+ EFI_SECURITY_VIOLATION if the validation fails.
+ - Validate the image is a supported image for this device. The function returns EFI_ABORTED if
+ the image is unsupported. The function can optionally provide more detailed information on
+ why the image is not a supported image.
+ - Validate the data from VendorCode if not null. Image validation must be performed before
+ VendorCode data validation. VendorCode data is ignored or considered invalid if image
+ validation failed. The function returns EFI_ABORTED if the data is invalid.
+
+ VendorCode enables vendor to implement vendor-specific firmware image update policy. Null if
+ the caller did not specify the policy or use the default policy. As an example, vendor can implement
+ a policy to allow an option to force a firmware image update when the abort reason is due to the new
+ firmware image version is older than the current firmware image version or bad image checksum.
+ Sensitive operations such as those wiping the entire firmware image and render the device to be
+ non-functional should be encoded in the image itself rather than passed with the VendorCode.
+ AbortReason enables vendor to have the option to provide a more detailed description of the abort
+ reason to the caller.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] ImageIndex A unique number identifying the firmware image(s) within the device.
+ The number is between 1 and DescriptorCount.
+ @param[in] Image Points to the new image.
+ @param[in] ImageSize Size of the new image in bytes.
+ @param[in] VendorCode This enables vendor to implement vendor-specific firmware image update policy.
+ Null indicates the caller did not specify the policy or use the default policy.
+ @param[in] Progress A function used by the driver to report the progress of the firmware update.
+ @param[out] AbortReason A pointer to a pointer to a null-terminated string providing more
+ details for the aborted operation. The buffer is allocated by this function
+ with AllocatePool(), and it is the caller's responsibility to free it with a
+ call to FreePool().
+
+ @retval EFI_SUCCESS The device was successfully updated with the new image.
+ @retval EFI_ABORTED The operation is aborted.
+ @retval EFI_INVALID_PARAMETER The Image was NULL.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+SetTheImage (
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN UINT8 ImageIndex,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode,
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,
+ OUT CHAR16 **AbortReason
+ );
+
+/**
+ Returns information about the firmware package.
+
+ This function returns package information.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[out] PackageVersion A version number that represents all the firmware images in the device.
+ The format is vendor specific and new version must have a greater value
+ than the old version. If PackageVersion is not supported, the value is
+ 0xFFFFFFFF. A value of 0xFFFFFFFE indicates that package version
+ comparison is to be performed using PackageVersionName. A value of
+ 0xFFFFFFFD indicates that package version update is in progress.
+ @param[out] PackageVersionName A pointer to a pointer to a null-terminated string representing
+ the package version name. The buffer is allocated by this function with
+ AllocatePool(), and it is the caller's responsibility to free it with a
+ call to FreePool().
+ @param[out] PackageVersionNameMaxLen The maximum length of package version name if device supports update of
+ package version name. A value of 0 indicates the device does not support
+ update of package version name. Length is the number of Unicode characters,
+ including the terminating null character.
+ @param[out] AttributesSupported Package attributes that are supported by this device. See 'Package Attribute
+ Definitions' for possible returned values of this parameter. A value of 1
+ indicates the attribute is supported and the current setting value is
+ indicated in AttributesSetting. A value of 0 indicates the attribute is not
+ supported and the current setting value in AttributesSetting is meaningless.
+ @param[out] AttributesSetting Package attributes. See 'Package Attribute Definitions' for possible returned
+ values of this parameter
+
+ @retval EFI_SUCCESS The package information was successfully returned.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+GetPackageInfo (
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ OUT UINT32 *PackageVersion,
+ OUT CHAR16 **PackageVersionName,
+ OUT UINT32 *PackageVersionNameMaxLen,
+ OUT UINT64 *AttributesSupported,
+ OUT UINT64 *AttributesSetting
+ );
+
+/**
+ Updates information about the firmware package.
+
+ This function updates package information.
+ This function returns EFI_UNSUPPORTED if the package information is not updatable.
+ VendorCode enables vendor to implement vendor-specific package information update policy.
+ Null if the caller did not specify this policy or use the default policy.
+
+ @param[in] This A pointer to the EFI_FIRMWARE_MANAGEMENT_PROTOCOL instance.
+ @param[in] Image Points to the authentication image.
+ Null if authentication is not required.
+ @param[in] ImageSize Size of the authentication image in bytes.
+ 0 if authentication is not required.
+ @param[in] VendorCode This enables vendor to implement vendor-specific firmware
+ image update policy.
+ Null indicates the caller did not specify this policy or use
+ the default policy.
+ @param[in] PackageVersion The new package version.
+ @param[in] PackageVersionName A pointer to the new null-terminated Unicode string representing
+ the package version name.
+ The string length is equal to or less than the value returned in
+ PackageVersionNameMaxLen.
+
+ @retval EFI_SUCCESS The device was successfully updated with the new package
+ information.
+ @retval EFI_INVALID_PARAMETER The PackageVersionName length is longer than the value
+ returned in PackageVersionNameMaxLen.
+ @retval EFI_UNSUPPORTED The operation is not supported.
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.
+
+**/
+EFI_STATUS
+EFIAPI
+SetPackageInfo (
+ IN EFI_FIRMWARE_MANAGEMENT_PROTOCOL *This,
+ IN CONST VOID *Image,
+ IN UINTN ImageSize,
+ IN CONST VOID *VendorCode,
+ IN UINT32 PackageVersion,
+ IN CONST CHAR16 *PackageVersionName
+ );
+
+#endif
diff --git a/FmpDevicePkg/FmpDxe/FmpDxe.inf b/FmpDevicePkg/FmpDxe/FmpDxe.inf
index cc57de975a..e3f9d174ef 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxe.inf
+++ b/FmpDevicePkg/FmpDxe/FmpDxe.inf
@@ -4,7 +4,7 @@
# information provided through PCDs and libraries.
#
# Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
-# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
@@ -17,6 +17,7 @@
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 1.0
ENTRY_POINT = FmpDxeEntryPoint
+ UNLOAD_IMAGE = UninstallFmpInstance
#
# The following information is for reference only and not required by the build tools.
@@ -26,6 +27,7 @@
[Sources]
FmpDxe.c
+ FmpDxe.h
DetectTestKey.c
VariableSupport.h
VariableSupport.c
diff --git a/FmpDevicePkg/FmpDxe/FmpDxeLib.inf b/FmpDevicePkg/FmpDxe/FmpDxeLib.inf
index 9722918b18..3b639fa74d 100644
--- a/FmpDevicePkg/FmpDxe/FmpDxeLib.inf
+++ b/FmpDevicePkg/FmpDxe/FmpDxeLib.inf
@@ -4,7 +4,7 @@
# information provided through PCDs and libraries.
#
# Copyright (c) 2016, Microsoft Corporation. All rights reserved.<BR>
-# Copyright (c) 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2018 - 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
@@ -18,6 +18,7 @@
VERSION_STRING = 1.0
LIBRARY_CLASS = NULL
CONSTRUCTOR = FmpDxeEntryPoint
+ DESTRUCTOR = FmpDxeLibDestructor
#
# The following information is for reference only and not required by the build tools.
@@ -27,6 +28,7 @@
[Sources]
FmpDxe.c
+ FmpDxe.h
DetectTestKey.c
VariableSupport.h
VariableSupport.c