\r
FmpSetImage() will receive untrusted input and do basic validation.\r
\r
- Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
which accompanies this distribution. The full text of the license may be found at\r
@param[in] ConfigData Points to the component configuration structure.\r
@param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[in] Progress A function used by the driver to report the progress of the firmware update.\r
+ @param[in] StartPercentage The start completion percentage value that may be used to report progress during the flash write operation.\r
+ @param[in] EndPercentage The end completion percentage value that may be used to report progress during the flash write operation.\r
\r
@retval EFI_SUCCESS The System Firmware image is updated.\r
@retval EFI_WRITE_PROTECTED The flash device is read only.\r
**/\r
EFI_STATUS\r
PerformUpdate (\r
- IN VOID *SystemFirmwareImage,\r
- IN UINTN SystemFirmwareImageSize,\r
- IN UPDATE_CONFIG_DATA *ConfigData,\r
- OUT UINT32 *LastAttemptVersion,\r
- OUT UINT32 *LastAttemptStatus\r
+ IN VOID *SystemFirmwareImage,\r
+ IN UINTN SystemFirmwareImageSize,\r
+ IN UPDATE_CONFIG_DATA *ConfigData,\r
+ OUT UINT32 *LastAttemptVersion,\r
+ OUT UINT32 *LastAttemptStatus,\r
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress,\r
+ IN UINTN StartPercentage,\r
+ IN UINTN EndPercentage\r
)\r
{\r
EFI_STATUS Status;\r
DEBUG((DEBUG_INFO, " BaseAddress - 0x%lx,", ConfigData->BaseAddress));\r
DEBUG((DEBUG_INFO, " ImageOffset - 0x%x,", ConfigData->ImageOffset));\r
DEBUG((DEBUG_INFO, " Legnth - 0x%x\n", ConfigData->Length));\r
- Status = PerformFlashWrite (\r
+ if (Progress != NULL) {\r
+ Progress (StartPercentage);\r
+ }\r
+ Status = PerformFlashWriteWithProgress (\r
ConfigData->FirmwareType,\r
ConfigData->BaseAddress,\r
ConfigData->AddressType,\r
(VOID *)((UINTN)SystemFirmwareImage + (UINTN)ConfigData->ImageOffset),\r
- ConfigData->Length\r
+ ConfigData->Length,\r
+ Progress,\r
+ StartPercentage,\r
+ EndPercentage\r
);\r
+ if (Progress != NULL) {\r
+ Progress (EndPercentage);\r
+ }\r
if (!EFI_ERROR(Status)) {\r
*LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
if (ConfigData->FirmwareType == PlatformFirmwareTypeNvRam) {\r
@param[in] ConfigImageSize The length of the config file image in bytes.\r
@param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[in] Progress A function used by the driver to report the progress of the firmware update.\r
\r
@retval EFI_SUCCESS The System Firmware image is updated.\r
@retval EFI_WRITE_PROTECTED The flash device is read only.\r
**/\r
EFI_STATUS\r
UpdateImage (\r
- IN VOID *SystemFirmwareImage,\r
- IN UINTN SystemFirmwareImageSize,\r
- IN VOID *ConfigImage,\r
- IN UINTN ConfigImageSize,\r
- OUT UINT32 *LastAttemptVersion,\r
- OUT UINT32 *LastAttemptStatus\r
+ IN VOID *SystemFirmwareImage,\r
+ IN UINTN SystemFirmwareImageSize,\r
+ IN VOID *ConfigImage,\r
+ IN UINTN ConfigImageSize,\r
+ OUT UINT32 *LastAttemptVersion,\r
+ OUT UINT32 *LastAttemptStatus,\r
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress\r
)\r
{\r
EFI_STATUS Status;\r
UPDATE_CONFIG_DATA *UpdateConfigData;\r
CONFIG_HEADER ConfigHeader;\r
UINTN Index;\r
+ UINTN TotalSize;\r
+ UINTN BytesWritten;\r
+ UINTN StartPercentage;\r
+ UINTN EndPercentage;\r
\r
if (ConfigImage == NULL) {\r
DEBUG((DEBUG_INFO, "PlatformUpdate (NoConfig):"));\r
DEBUG((DEBUG_INFO, " BaseAddress - 0x%x,", 0));\r
DEBUG((DEBUG_INFO, " Length - 0x%x\n", SystemFirmwareImageSize));\r
// ASSUME the whole System Firmware include NVRAM region.\r
- Status = PerformFlashWrite (\r
+ StartPercentage = 0;\r
+ EndPercentage = 100;\r
+ if (Progress != NULL) {\r
+ Progress (StartPercentage);\r
+ }\r
+ Status = PerformFlashWriteWithProgress (\r
PlatformFirmwareTypeNvRam,\r
0,\r
FlashAddressTypeRelativeAddress,\r
SystemFirmwareImage,\r
- SystemFirmwareImageSize\r
+ SystemFirmwareImageSize,\r
+ Progress,\r
+ StartPercentage,\r
+ EndPercentage\r
);\r
+ if (Progress != NULL) {\r
+ Progress (EndPercentage);\r
+ }\r
if (!EFI_ERROR(Status)) {\r
*LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
mNvRamUpdated = TRUE;\r
DEBUG((DEBUG_INFO, "ConfigHeader.NumOfUpdates - 0x%x\n", ConfigHeader.NumOfUpdates));\r
DEBUG((DEBUG_INFO, "PcdEdkiiSystemFirmwareFileGuid - %g\n", PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid)));\r
\r
+ TotalSize = 0;\r
+ for (Index = 0; Index < ConfigHeader.NumOfUpdates; Index++) {\r
+ if (CompareGuid(&ConfigData[Index].FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) {\r
+ TotalSize = TotalSize + ConfigData[Index].Length;\r
+ }\r
+ }\r
+\r
+ BytesWritten = 0;\r
Index = 0;\r
UpdateConfigData = ConfigData;\r
while (Index < ConfigHeader.NumOfUpdates) {\r
if (CompareGuid(&UpdateConfigData->FileGuid, PcdGetPtr(PcdEdkiiSystemFirmwareFileGuid))) {\r
DEBUG((DEBUG_INFO, "FileGuid - %g (processing)\n", &UpdateConfigData->FileGuid));\r
+ StartPercentage = (BytesWritten * 100) / TotalSize;\r
+ EndPercentage = ((BytesWritten + UpdateConfigData->Length) * 100) / TotalSize;\r
Status = PerformUpdate (\r
SystemFirmwareImage,\r
SystemFirmwareImageSize,\r
UpdateConfigData,\r
LastAttemptVersion,\r
- LastAttemptStatus\r
+ LastAttemptStatus,\r
+ Progress,\r
+ StartPercentage,\r
+ EndPercentage\r
);\r
//\r
// Shall updates be serialized so that if an update is not successfully completed,\r
DEBUG((DEBUG_INFO, "FileGuid - %g (ignored)\n", &UpdateConfigData->FileGuid));\r
}\r
\r
+ BytesWritten += UpdateConfigData->Length;\r
+\r
Index++;\r
UpdateConfigData++;\r
}\r
@param[in] ImageSize The size of the EDKII system FMP capsule image in bytes.\r
@param[out] LastAttemptVersion The last attempt version, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
@param[out] LastAttemptStatus The last attempt status, which will be recorded in ESRT and FMP EFI_FIRMWARE_IMAGE_DESCRIPTOR.\r
+ @param[in] Progress A function used by the driver to report the progress of the firmware update.\r
\r
@retval EFI_SUCCESS EDKII system FMP capsule passes authentication and the System Firmware image is updated.\r
@retval EFI_SECURITY_VIOLATION EDKII system FMP capsule fails authentication and the System Firmware image is not updated.\r
**/\r
EFI_STATUS\r
SystemFirmwareAuthenticatedUpdate (\r
- IN VOID *Image,\r
- IN UINTN ImageSize,\r
- OUT UINT32 *LastAttemptVersion,\r
- OUT UINT32 *LastAttemptStatus\r
+ IN VOID *Image,\r
+ IN UINTN ImageSize,\r
+ OUT UINT32 *LastAttemptVersion,\r
+ OUT UINT32 *LastAttemptStatus,\r
+ IN EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS Progress\r
)\r
{\r
EFI_STATUS Status;\r
ExtractConfigImage(AuthenticatedImage, AuthenticatedImageSize, &ConfigImage, &ConfigImageSize);\r
\r
DEBUG((DEBUG_INFO, "UpdateImage ...\n"));\r
- Status = UpdateImage(SystemFirmwareImage, SystemFirmwareImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus);\r
+ Status = UpdateImage(SystemFirmwareImage, SystemFirmwareImageSize, ConfigImage, ConfigImageSize, LastAttemptVersion, LastAttemptStatus, Progress);\r
if (EFI_ERROR(Status)) {\r
DEBUG((DEBUG_INFO, "UpdateImage - %r\n", Status));\r
return Status;\r
@retval EFI_ABORTED The operation is aborted.\r
@retval EFI_INVALID_PARAMETER The Image was NULL.\r
@retval EFI_UNSUPPORTED The operation is not supported.\r
- @retval EFI_SECURITY_VIOLATIO The operation could not be performed due to an authentication failure.\r
+ @retval EFI_SECURITY_VIOLATION The operation could not be performed due to an authentication failure.\r
\r
**/\r
EFI_STATUS\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
- Status = SystemFirmwareAuthenticatedUpdate((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus);\r
- DEBUG((DEBUG_INFO, "SetImage - LastAttemp Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));\r
+ Status = SystemFirmwareAuthenticatedUpdate((VOID *)Image, ImageSize, &SystemFmpPrivate->LastAttempt.LastAttemptVersion, &SystemFmpPrivate->LastAttempt.LastAttemptStatus, Progress);\r
+ DEBUG((DEBUG_INFO, "SetImage - LastAttempt Version - 0x%x, State - 0x%x\n", SystemFmpPrivate->LastAttempt.LastAttemptVersion, SystemFmpPrivate->LastAttempt.LastAttemptStatus));\r
\r
//\r
// If NVRAM is updated, we should no longer touch variable services, because\r
return Status;\r
}\r
\r
+/**\r
+ Get the set of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures from an FMP Protocol.\r
+\r
+ @param[in] Handle Handle with an FMP Protocol or a System FMP\r
+ Protocol.\r
+ @param[in] ProtocolGuid Pointer to the FMP Protocol GUID or System FMP\r
+ Protocol GUID.\r
+ @param[out] FmpImageInfoCount Pointer to the number of\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR structures.\r
+ @param[out] DescriptorSize Pointer to the size, in bytes, of each\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR structure.\r
+\r
+ @return NULL No EFI_FIRMWARE_IMAGE_DESCRIPTOR structures found.\r
+ @return !NULL Pointer to a buffer of EFI_FIRMWARE_IMAGE_DESCRIPTOR structures\r
+ allocated using AllocatePool(). Caller must free buffer with\r
+ FreePool().\r
+**/\r
+EFI_FIRMWARE_IMAGE_DESCRIPTOR *\r
+GetFmpImageDescriptors (\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_GUID *ProtocolGuid,\r
+ OUT UINT8 *FmpImageInfoCount,\r
+ OUT UINTN *DescriptorSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ UINTN ImageInfoSize;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
+ UINT32 FmpImageInfoDescriptorVer;\r
+ UINT32 PackageVersion;\r
+ CHAR16 *PackageVersionName;\r
+\r
+ *FmpImageInfoCount = 0;\r
+ *DescriptorSize = 0;\r
+\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ ProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Determine the size required for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
+ //\r
+ ImageInfoSize = 0;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp, // FMP Pointer\r
+ &ImageInfoSize, // Buffer Size (in this case 0)\r
+ NULL, // NULL so we can get size\r
+ &FmpImageInfoDescriptorVer, // DescriptorVersion\r
+ FmpImageInfoCount, // DescriptorCount\r
+ DescriptorSize, // DescriptorSize\r
+ &PackageVersion, // PackageVersion\r
+ &PackageVersionName // PackageVersionName\r
+ );\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Unexpected Failure. Status = %r\n", Status));\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer for the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
+ //\r
+ FmpImageInfoBuf = NULL;\r
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to allocate memory for descriptors.\n"));\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Retrieve the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
+ //\r
+ PackageVersionName = NULL;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize, // ImageInfoSize\r
+ FmpImageInfoBuf, // ImageInfo\r
+ &FmpImageInfoDescriptorVer, // DescriptorVersion\r
+ FmpImageInfoCount, // DescriptorCount\r
+ DescriptorSize, // DescriptorSize\r
+ &PackageVersion, // PackageVersion\r
+ &PackageVersionName // PackageVersionName\r
+ );\r
+\r
+ //\r
+ // Free unused PackageVersionName return buffer\r
+ //\r
+ if (PackageVersionName != NULL) {\r
+ FreePool (PackageVersionName);\r
+ PackageVersionName = NULL;\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failure in GetImageInfo. Status = %r\n", Status));\r
+ if (FmpImageInfoBuf != NULL) {\r
+ FreePool (FmpImageInfoBuf);\r
+ }\r
+ return NULL;\r
+ }\r
+\r
+ return FmpImageInfoBuf;\r
+}\r
+\r
+/**\r
+ Search for handles with an FMP protocol whose EFI_FIRMWARE_IMAGE_DESCRIPTOR\r
+ ImageTypeId matches the ImageTypeId produced by this module.\r
+\r
+ @param[in] ProtocolGuid Pointer to the GUID of the protocol to search.\r
+ @param[out] HandleCount Pointer to the number of returned handles.\r
+\r
+ @return NULL No matching handles found.\r
+ @return !NULL Pointer to a buffer of handles allocated using AllocatePool().\r
+ Caller must free buffer with FreePool().\r
+**/\r
+EFI_HANDLE *\r
+FindMatchingFmpHandles (\r
+ IN EFI_GUID *ProtocolGuid,\r
+ OUT UINTN *HandleCount\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN TempHandleCount;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN Index;\r
+ UINTN Index2;\r
+ UINTN Index3;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *OriginalFmpImageInfoBuf;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
+ UINT8 FmpImageInfoCount;\r
+ UINTN DescriptorSize;\r
+ BOOLEAN MatchFound;\r
+\r
+ *HandleCount = 0;\r
+ TempHandleCount = 0;\r
+ HandleBuffer = NULL;\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ ProtocolGuid,\r
+ NULL,\r
+ &TempHandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return NULL;\r
+ }\r
+\r
+ for (Index = 0; Index < TempHandleCount; Index++) {\r
+ OriginalFmpImageInfoBuf = GetFmpImageDescriptors (\r
+ HandleBuffer[Index],\r
+ ProtocolGuid,\r
+ &FmpImageInfoCount,\r
+ &DescriptorSize\r
+ );\r
+\r
+ //\r
+ // Loop through the set of EFI_FIRMWARE_IMAGE_DESCRIPTORs.\r
+ //\r
+ FmpImageInfoBuf = OriginalFmpImageInfoBuf;\r
+ MatchFound = FALSE;\r
+ for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {\r
+ for (Index3 = 0; Index3 < mSystemFmpPrivate->DescriptorCount; Index3++) {\r
+ MatchFound = CompareGuid (\r
+ &FmpImageInfoBuf->ImageTypeId,\r
+ &mSystemFmpPrivate->ImageDescriptor[Index3].ImageTypeId\r
+ );\r
+ if (MatchFound) {\r
+ break;\r
+ }\r
+ }\r
+ if (MatchFound) {\r
+ break;\r
+ }\r
+ //\r
+ // Increment the buffer pointer ahead by the size of the descriptor\r
+ //\r
+ FmpImageInfoBuf = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)(((UINT8 *)FmpImageInfoBuf) + DescriptorSize);\r
+ }\r
+ if (MatchFound) {\r
+ HandleBuffer[*HandleCount] = HandleBuffer[Index];\r
+ (*HandleCount)++;\r
+ }\r
+\r
+ FreePool (OriginalFmpImageInfoBuf);\r
+ }\r
+\r
+ if ((*HandleCount) == 0) {\r
+ //\r
+ // No any matching handle.\r
+ //\r
+ FreePool (HandleBuffer);\r
+ return NULL;\r
+ }\r
+ return HandleBuffer;\r
+}\r
+\r
+/**\r
+ Uninstall System FMP Protocol instances that may have been installed by\r
+ SystemFirmwareUpdateDxe drivers dispatches by other capsules.\r
+\r
+ @retval EFI_SUCCESS All System FMP Protocols found were uninstalled.\r
+ @return Other One or more System FMP Protocols could not be uninstalled.\r
+\r
+**/\r
+EFI_STATUS\r
+UninstallMatchingSystemFmpProtocols (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *SystemFmp;\r
+\r
+ //\r
+ // Uninstall SystemFmpProtocol instances that may have been produced by\r
+ // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.\r
+ //\r
+ HandleBuffer = FindMatchingFmpHandles (\r
+ &gSystemFmpProtocolGuid,\r
+ &HandleCount\r
+ );\r
+ DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching System FMP instances\n", HandleCount));\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ Status = gBS->HandleProtocol(\r
+ HandleBuffer[Index],\r
+ &gSystemFmpProtocolGuid,\r
+ (VOID **)&SystemFmp\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ continue;\r
+ }\r
+ DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Uninstall SystemFmp produced by another capsule\n"));\r
+ Status = gBS->UninstallProtocolInterface (\r
+ HandleBuffer[Index],\r
+ &gSystemFmpProtocolGuid,\r
+ SystemFmp\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: Failed to uninstall SystemFmp %r. Exiting.\n", Status));\r
+ FreePool (HandleBuffer);\r
+ return Status;\r
+ }\r
+ }\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
System FMP module entrypoint\r
\r
- @param ImageHandle The firmware allocated handle for the EFI image.\r
- @param SystemTable A pointer to the EFI System Table.\r
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
\r
- @return EFI_SUCCESS System FMP module is initialized.\r
+ @retval EFI_SUCCESS System FMP module is initialized.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources avaulable to\r
+ initialize this module.\r
+ @retval Other System FMP Protocols could not be uninstalled.\r
+ @retval Other System FMP Protocol could not be installed.\r
+ @retval Other FMP Protocol could not be installed.\r
**/\r
EFI_STATUS\r
EFIAPI\r
SystemFirmwareUpdateMainDxe (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
\r
//\r
// Initialize SystemFmpPrivateData\r
//\r
- mSystemFmpPrivate = AllocateZeroPool (sizeof(SYSTEM_FMP_PRIVATE_DATA));\r
+ mSystemFmpPrivate = AllocateZeroPool (sizeof (SYSTEM_FMP_PRIVATE_DATA));\r
if (mSystemFmpPrivate == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Status = InitializePrivateData(mSystemFmpPrivate);\r
- if (EFI_ERROR(Status)) {\r
- FreePool(mSystemFmpPrivate);\r
+ Status = InitializePrivateData (mSystemFmpPrivate);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (mSystemFmpPrivate);\r
mSystemFmpPrivate = NULL;\r
return Status;\r
}\r
\r
//\r
- // Install FMP protocol.\r
+ // Uninstall SystemFmpProtocol instances that may have been produced by\r
+ // the SystemFirmwareUpdate drivers in FVs dispatched by other capsules.\r
//\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &mSystemFmpPrivate->Handle,\r
- &gEfiFirmwareManagementProtocolGuid,\r
- &mSystemFmpPrivate->Fmp,\r
- &gSystemFmpProtocolGuid,\r
- &mSystemFmpPrivate->Fmp,\r
- NULL\r
- );\r
+ Status = UninstallMatchingSystemFmpProtocols ();\r
if (EFI_ERROR (Status)) {\r
- FreePool(mSystemFmpPrivate);\r
+ FreePool (mSystemFmpPrivate);\r
mSystemFmpPrivate = NULL;\r
return Status;\r
}\r
\r
+ //\r
+ // Look for a handle with matching Firmware Management Protocol\r
+ //\r
+ HandleCount = 0;\r
+ HandleBuffer = FindMatchingFmpHandles (\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ &HandleCount\r
+ );\r
+ DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Found %d matching FMP instances\n", HandleCount));\r
+\r
+ switch (HandleCount) {\r
+ case 0:\r
+ //\r
+ // Install FMP protocol onto a new handle.\r
+ //\r
+ DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install FMP onto a new handle\n"));\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &mSystemFmpPrivate->Handle,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ &mSystemFmpPrivate->Fmp,\r
+ NULL\r
+ );\r
+ break;\r
+ case 1:\r
+ //\r
+ // Install System FMP protocol onto handle with matching FMP Protocol\r
+ //\r
+ DEBUG ((DEBUG_INFO, "SystemFirmwareUpdateDxe: Install System FMP onto matching FMP handle\n"));\r
+ mSystemFmpPrivate->Handle = HandleBuffer[0];\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &HandleBuffer[0],\r
+ &gSystemFmpProtocolGuid,\r
+ &mSystemFmpPrivate->Fmp,\r
+ NULL\r
+ );\r
+ break;\r
+ default:\r
+ //\r
+ // More than one matching handle is not expected. Unload driver.\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "SystemFirmwareUpdateDxe: More than one matching FMP handle. Unload driver.\n"));\r
+ Status = EFI_DEVICE_ERROR;\r
+ break;\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (mSystemFmpPrivate);\r
+ mSystemFmpPrivate = NULL;\r
+ }\r
+\r
return Status;\r
}\r