\r
FmpSetImage() will receive untrusted input and do basic validation.\r
\r
- Copyright (c) 2016, 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
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\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
VOID *AuthenticatedImage;\r
UINTN AuthenticatedImageSize;\r
\r
+ AuthenticatedImage = NULL;\r
+ AuthenticatedImageSize = 0;\r
+\r
DEBUG((DEBUG_INFO, "SystemFirmwareAuthenticatedUpdate...\n"));\r
\r
Status = CapsuleAuthenticateSystemFirmware(Image, ImageSize, FALSE, LastAttemptVersion, LastAttemptStatus, &AuthenticatedImage, &AuthenticatedImageSize);\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
// the current variable driver may not manage the new NVRAM region.\r
//\r
if (mNvRamUpdated) {\r
- DEBUG ((DEBUG_INFO, "NvRamUpdated, Update Variable Serivces\n"));\r
+ DEBUG ((DEBUG_INFO, "NvRamUpdated, Update Variable Services\n"));\r
gRT->GetVariable = GetVariableHook;\r
gRT->GetNextVariableName = GetNextVariableNameHook;\r
gRT->SetVariable = SetVariableHook;\r
sizeof(SystemFmpPrivate->LastAttempt),\r
&SystemFmpPrivate->LastAttempt\r
);\r
- DEBUG((DEBUG_INFO, "SetLastAttemp - %r\n", VarStatus));\r
+ DEBUG((DEBUG_INFO, "SetLastAttempt - %r\n", VarStatus));\r
\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