#include <Library/CapsuleLib.h>\r
#include <Library/DevicePathLib.h>\r
#include <Library/UefiLib.h>\r
-#include <Library/PcdLib.h>\r
#include <Library/BmpSupportLib.h>\r
\r
#include <Protocol/GraphicsOutput.h>\r
#include <Protocol/EsrtManagement.h>\r
#include <Protocol/FirmwareManagement.h>\r
+#include <Protocol/FirmwareManagementProgress.h>\r
#include <Protocol/DevicePath.h>\r
\r
EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;\r
BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;\r
EFI_EVENT mDxeCapsuleLibEndOfDxeEvent = NULL;\r
\r
+EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *mFmpProgress = NULL;\r
+\r
/**\r
Initialize capsule related variables.\r
**/\r
Function indicate the current completion progress of the firmware\r
update. Platform may override with own specific progress function.\r
\r
- @param[in] Completion A value between 1 and 100 indicating the current completion progress of the firmware update\r
+ @param[in] Completion A value between 1 and 100 indicating the current\r
+ completion progress of the firmware update\r
\r
- @retval EFI_SUCESS Input capsule is a correct FMP capsule.\r
+ @retval EFI_SUCESS The capsule update progress was updated.\r
+ @retval EFI_INVALID_PARAMETER Completion is greater than 100%.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-Update_Image_Progress (\r
+UpdateImageProgress (\r
IN UINTN Completion\r
- )\r
-{\r
- return EFI_SUCCESS;\r
-}\r
+ );\r
\r
/**\r
Return if this CapsuleGuid is a FMP capsule GUID or not.\r
//\r
if (Index > 0) {\r
if (ItemOffsetList[Index] <= ItemOffsetList[Index - 1]) {\r
- DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index, ItemOffsetList[Index - 1]));\r
+ DEBUG((DEBUG_ERROR, "ItemOffsetList[%d](0x%lx) < ItemOffsetList[%d](0x%x)\n", Index, ItemOffsetList[Index], Index - 1, ItemOffsetList[Index - 1]));\r
return EFI_INVALID_PARAMETER;\r
}\r
}\r
}\r
FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index];\r
\r
- if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) {\r
- DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize));\r
- return EFI_INVALID_PARAMETER;\r
- }\r
FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER);\r
if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) ||\r
(ImageHeader->Version < 1)) {\r
if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
}\r
+ if (FmpImageSize < FmpImageHeaderSize) {\r
+ DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize, FmpImageHeaderSize));\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
// No overflow\r
if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) {\r
UINTN Width;\r
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
\r
- ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1);\r
- PayloadSize = CapsuleHeader->CapsuleImageSize - sizeof(EFI_CAPSULE_HEADER);\r
+ //\r
+ // UX capsule doesn't have extended header entries.\r
+ //\r
+ if (CapsuleHeader->HeaderSize != sizeof (EFI_CAPSULE_HEADER)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)((UINTN) CapsuleHeader + CapsuleHeader->HeaderSize);\r
+ //\r
+ // (CapsuleImageSize > HeaderSize) is guaranteed by IsValidCapsuleHeader().\r
+ //\r
+ PayloadSize = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize;\r
+\r
+ //\r
+ // Make sure the image payload at least contain the DISPLAY_DISPLAY_PAYLOAD header.\r
+ // Further size check is performed by the logic translating BMP to GOP BLT.\r
+ //\r
+ if (PayloadSize <= sizeof (DISPLAY_DISPLAY_PAYLOAD)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
if (ImagePayload->Version != 1) {\r
return EFI_UNSUPPORTED;\r
FreePool(FmpImageInfoBuf);\r
}\r
\r
+ FreePool (HandleBuffer);\r
+\r
return ;\r
}\r
\r
\r
@param[in] UpdateImageTypeId Used to identify device firmware targeted by this update.\r
@param[in] UpdateHardwareInstance The HardwareInstance to target with this update.\r
- @param[in,out] NoHandles The number of handles returned in Buffer.\r
- @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles.\r
-\r
- @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of\r
- handles in Buffer was returned in NoHandles.\r
+ @param[out] NoHandles The number of handles returned in HandleBuf.\r
+ @param[out] HandleBuf A pointer to the buffer to return the requested array of handles.\r
+ @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for\r
+ the requested array of handles.\r
+\r
+ @retval EFI_SUCCESS The array of handles and their reset required flag were returned in\r
+ HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf\r
+ was returned in NoHandles.\r
@retval EFI_NOT_FOUND No handles match the search.\r
@retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results.\r
**/\r
GetFmpHandleBufferByType (\r
IN EFI_GUID *UpdateImageTypeId,\r
IN UINT64 UpdateHardwareInstance,\r
- IN OUT UINTN *NoHandles,\r
- OUT EFI_HANDLE **Buffer\r
+ OUT UINTN *NoHandles, OPTIONAL\r
+ OUT EFI_HANDLE **HandleBuf, OPTIONAL\r
+ OUT BOOLEAN **ResetRequiredBuf OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
EFI_HANDLE *HandleBuffer;\r
UINTN NumberOfHandles;\r
EFI_HANDLE *MatchedHandleBuffer;\r
+ BOOLEAN *MatchedResetRequiredBuffer;\r
UINTN MatchedNumberOfHandles;\r
EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
UINTN Index;\r
UINTN Index2;\r
EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;\r
\r
- *NoHandles = 0;\r
- *Buffer = NULL;\r
+ if (NoHandles != NULL) {\r
+ *NoHandles = 0;\r
+ }\r
+ if (HandleBuf != NULL) {\r
+ *HandleBuf = NULL;\r
+ }\r
+ if (ResetRequiredBuf != NULL) {\r
+ *ResetRequiredBuf = NULL;\r
+ }\r
\r
Status = gBS->LocateHandleBuffer (\r
ByProtocol,\r
}\r
\r
MatchedNumberOfHandles = 0;\r
- MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles);\r
- if (MatchedHandleBuffer == NULL) {\r
- FreePool (HandleBuffer);\r
- return EFI_OUT_OF_RESOURCES;\r
+\r
+ MatchedHandleBuffer = NULL;\r
+ if (HandleBuf != NULL) {\r
+ MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles);\r
+ if (MatchedHandleBuffer == NULL) {\r
+ FreePool (HandleBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
+ MatchedResetRequiredBuffer = NULL;\r
+ if (ResetRequiredBuf != NULL) {\r
+ MatchedResetRequiredBuffer = AllocateZeroPool (sizeof(BOOLEAN) * NumberOfHandles);\r
+ if (MatchedResetRequiredBuffer == NULL) {\r
+ if (MatchedHandleBuffer != NULL) {\r
+ FreePool (MatchedHandleBuffer);\r
+ }\r
+ FreePool (HandleBuffer);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
}\r
\r
for (Index = 0; Index < NumberOfHandles; Index++) {\r
if ((UpdateHardwareInstance == 0) ||\r
((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&\r
(UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) {\r
- MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];\r
+ if (MatchedHandleBuffer != NULL) {\r
+ MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];\r
+ }\r
+ if (MatchedResetRequiredBuffer != NULL) {\r
+ MatchedResetRequiredBuffer[MatchedNumberOfHandles] = (((TempFmpImageInfo->AttributesSupported &\r
+ IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) &&\r
+ ((TempFmpImageInfo->AttributesSetting &\r
+ IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0));\r
+ }\r
MatchedNumberOfHandles++;\r
break;\r
}\r
FreePool(FmpImageInfoBuf);\r
}\r
\r
+ FreePool (HandleBuffer);\r
+\r
if (MatchedNumberOfHandles == 0) {\r
return EFI_NOT_FOUND;\r
}\r
\r
- *NoHandles = MatchedNumberOfHandles;\r
- *Buffer = MatchedHandleBuffer;\r
+ if (NoHandles != NULL) {\r
+ *NoHandles = MatchedNumberOfHandles;\r
+ }\r
+ if (HandleBuf != NULL) {\r
+ *HandleBuf = MatchedHandleBuffer;\r
+ }\r
+ if (ResetRequiredBuf != NULL) {\r
+ *ResetRequiredBuf = MatchedResetRequiredBuffer;\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
UINT8 *Image;\r
VOID *VendorCode;\r
CHAR16 *AbortReason;\r
+ EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback;\r
\r
Status = gBS->HandleProtocol(\r
Handle,\r
return Status;\r
}\r
\r
+ //\r
+ // Lookup Firmware Management Progress Protocol before SetImage() is called\r
+ // This is an optional protocol that may not be present on Handle.\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ Handle,\r
+ &gEdkiiFirmwareManagementProgressProtocolGuid,\r
+ (VOID **)&mFmpProgress\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ mFmpProgress = NULL;\r
+ }\r
+\r
if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
Image = (UINT8 *)(ImageHeader + 1);\r
} else {\r
DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));\r
}\r
DEBUG((DEBUG_INFO, "\n"));\r
+\r
+ //\r
+ // Before calling SetImage(), reset the progress bar to 0%\r
+ //\r
+ ProgressCallback = UpdateImageProgress;\r
+ Status = UpdateImageProgress (0);\r
+ if (EFI_ERROR (Status)) {\r
+ ProgressCallback = NULL;\r
+ }\r
+\r
Status = Fmp->SetImage(\r
Fmp,\r
ImageHeader->UpdateImageIndex, // ImageIndex\r
Image, // Image\r
ImageHeader->UpdateImageSize, // ImageSize\r
VendorCode, // VendorCode\r
- Update_Image_Progress, // Progress\r
+ ProgressCallback, // Progress\r
&AbortReason // AbortReason\r
);\r
+ //\r
+ // Set the progress bar to 100% after returning from SetImage()\r
+ //\r
+ if (ProgressCallback != NULL) {\r
+ UpdateImageProgress (100);\r
+ }\r
+\r
DEBUG((DEBUG_INFO, "Fmp->SetImage - %r\n", Status));\r
if (AbortReason != NULL) {\r
DEBUG ((DEBUG_ERROR, "%s\n", AbortReason));\r
FreePool(AbortReason);\r
}\r
\r
+ //\r
+ // Clear mFmpProgress after SetImage() returns\r
+ //\r
+ mFmpProgress = NULL;\r
+\r
return Status;\r
}\r
\r
\r
//\r
// Update EsrtEntry For V1, V2 FMP instance.\r
- // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface\r
+ // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface\r
//\r
FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);\r
if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {\r
\r
This function need support nested FMP capsule.\r
\r
- @param[in] CapsuleHeader Points to a capsule header.\r
+ @param[in] CapsuleHeader Points to a capsule header.\r
+ @param[out] ResetRequired Indicates whether reset is required or not.\r
\r
@retval EFI_SUCESS Process Capsule Image successfully.\r
@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
**/\r
EFI_STATUS\r
ProcessFmpCapsuleImage (\r
- IN EFI_CAPSULE_HEADER *CapsuleHeader\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
+ OUT BOOLEAN *ResetRequired OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
UINT32 ItemNum;\r
UINTN Index;\r
EFI_HANDLE *HandleBuffer;\r
+ BOOLEAN *ResetRequiredBuffer;\r
UINTN NumberOfHandles;\r
UINTN DriverLen;\r
UINT64 UpdateHardwareInstance;\r
BOOLEAN Abort;\r
\r
if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
- return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));\r
+ return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);\r
}\r
\r
NotReady = FALSE;\r
&ImageHeader->UpdateImageTypeId,\r
UpdateHardwareInstance,\r
&NumberOfHandles,\r
- &HandleBuffer\r
+ &HandleBuffer,\r
+ &ResetRequiredBuffer\r
);\r
- if (EFI_ERROR(Status)) {\r
+ if (EFI_ERROR(Status) ||\r
+ (HandleBuffer == NULL) ||\r
+ (ResetRequiredBuffer == NULL)) {\r
NotReady = TRUE;\r
RecordFmpCapsuleStatus (\r
NULL,\r
);\r
if (Status != EFI_SUCCESS) {\r
Abort = TRUE;\r
+ } else {\r
+ if (ResetRequired != NULL) {\r
+ *ResetRequired |= ResetRequiredBuffer[Index2];\r
+ }\r
}\r
\r
RecordFmpCapsuleStatus (\r
if (HandleBuffer != NULL) {\r
FreePool(HandleBuffer);\r
}\r
+ if (ResetRequiredBuffer != NULL) {\r
+ FreePool(ResetRequiredBuffer);\r
+ }\r
}\r
\r
if (NotReady) {\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_SYSTEM_RESOURCE_TABLE *Esrt;\r
EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;\r
UINTN Index;\r
BOOLEAN EsrtGuidFound;\r
}\r
\r
//\r
- // Check ESRT configuration table\r
+ // Check Firmware Management Protocols\r
//\r
if (!EsrtGuidFound) {\r
- Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);\r
+ Status = GetFmpHandleBufferByType (\r
+ &CapsuleHeader->CapsuleGuid,\r
+ 0,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
if (!EFI_ERROR(Status)) {\r
- ASSERT (Esrt != NULL);\r
- EsrtEntry = (VOID *)(Esrt + 1);\r
- for (Index = 0; Index < Esrt->FwResourceCount; Index++, EsrtEntry++) {\r
- if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {\r
- EsrtGuidFound = TRUE;\r
- break;\r
- }\r
- }\r
+ EsrtGuidFound = TRUE;\r
}\r
}\r
}\r
}\r
\r
if (IsFmpCapsule(CapsuleHeader)) {\r
+ //\r
+ // Fake capsule header is valid case in QueryCapsuleCpapbilities().\r
+ //\r
+ if (CapsuleHeader->HeaderSize == CapsuleHeader->CapsuleImageSize) {\r
+ return EFI_SUCCESS;\r
+ }\r
//\r
// Check layout of FMP capsule\r
//\r
Caution: This function may receive untrusted input.\r
\r
@param[in] CapsuleHeader Points to a capsule header.\r
+ @param[out] ResetRequired Indicates whether reset is required or not.\r
\r
@retval EFI_SUCESS Process Capsule Image successfully.\r
@retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-ProcessCapsuleImage (\r
- IN EFI_CAPSULE_HEADER *CapsuleHeader\r
+ProcessThisCapsuleImage (\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
+ OUT BOOLEAN *ResetRequired OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
}\r
\r
//\r
- // Press EFI FMP Capsule\r
+ // Process EFI FMP Capsule\r
//\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));\r
- Status = ProcessFmpCapsuleImage(CapsuleHeader);\r
+ Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));\r
\r
return Status;\r
return EFI_UNSUPPORTED;\r
}\r
\r
+/**\r
+ The firmware implements to process the capsule image.\r
+\r
+ Caution: This function may receive untrusted input.\r
+\r
+ @param[in] CapsuleHeader Points to a capsule header.\r
+\r
+ @retval EFI_SUCESS Process Capsule Image successfully.\r
+ @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware.\r
+ @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted.\r
+ @retval EFI_OUT_OF_RESOURCES Not enough memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessCapsuleImage (\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader\r
+ )\r
+{\r
+ return ProcessThisCapsuleImage (CapsuleHeader, NULL);\r
+}\r
+\r
/**\r
Callback function executed when the EndOfDxe event group is signaled.\r
\r