#include <Protocol/FirmwareManagement.h>\r
#include <Protocol/DevicePath.h>\r
\r
-BOOLEAN mAreAllImagesProcessed;\r
-\r
EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;\r
BOOLEAN mIsVirtualAddrConverted = FALSE;\r
BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;\r
VOID\r
);\r
\r
-/**\r
- Check if this FMP capsule is processed.\r
-\r
- @param[in] CapsuleHeader The capsule image header\r
- @param[in] PayloadIndex FMP payload index\r
- @param[in] ImageHeader FMP image header\r
-\r
- @retval TRUE This FMP capsule is processed.\r
- @retval FALSE This FMP capsule is not processed.\r
-**/\r
-BOOLEAN\r
-IsFmpCapsuleProcessed (\r
- IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
- IN UINTN PayloadIndex,\r
- IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader\r
- );\r
-\r
/**\r
Record capsule status variable.\r
\r
}\r
}\r
\r
+/**\r
+ Dump all FMP information.\r
+**/\r
+VOID\r
+DumpAllFmpInfo (\r
+ VOID\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN NumberOfHandles;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ UINTN Index;\r
+ UINTN ImageInfoSize;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
+ UINT32 FmpImageInfoDescriptorVer;\r
+ UINT8 FmpImageInfoCount;\r
+ UINTN DescriptorSize;\r
+ UINT32 PackageVersion;\r
+ CHAR16 *PackageVersionName;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ NULL,\r
+ &NumberOfHandles,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return ;\r
+ }\r
+\r
+ for (Index = 0; Index < NumberOfHandles; Index++) {\r
+ Status = gBS->HandleProtocol(\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ ImageInfoSize = 0;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ continue;\r
+ }\r
+\r
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\r
+ continue;\r
+ }\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
+ if (EFI_ERROR(Status)) {\r
+ FreePool(FmpImageInfoBuf);\r
+ continue;\r
+ }\r
+\r
+ DEBUG((DEBUG_INFO, "FMP (%d) ImageInfo:\n", Index));\r
+ DumpFmpImageInfo(\r
+ ImageInfoSize, // ImageInfoSize\r
+ FmpImageInfoBuf, // ImageInfo\r
+ FmpImageInfoDescriptorVer, // DescriptorVersion\r
+ FmpImageInfoCount, // DescriptorCount\r
+ DescriptorSize, // DescriptorSize\r
+ PackageVersion, // PackageVersion\r
+ PackageVersionName // PackageVersionName\r
+ );\r
+\r
+ if (PackageVersionName != NULL) {\r
+ FreePool(PackageVersionName);\r
+ }\r
+\r
+ FreePool(FmpImageInfoBuf);\r
+ }\r
+\r
+ return ;\r
+}\r
+\r
+/**\r
+ Get FMP handle by ImageTypeId and HardwareInstance.\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
+ @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
+EFI_STATUS\r
+GetFmpHandleBufferByType (\r
+ IN EFI_GUID *UpdateImageTypeId,\r
+ IN UINT64 UpdateHardwareInstance,\r
+ IN OUT UINTN *NoHandles,\r
+ OUT EFI_HANDLE **Buffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN NumberOfHandles;\r
+ EFI_HANDLE *MatchedHandleBuffer;\r
+ UINTN MatchedNumberOfHandles;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ UINTN Index;\r
+ UINTN ImageInfoSize;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
+ UINT32 FmpImageInfoDescriptorVer;\r
+ UINT8 FmpImageInfoCount;\r
+ UINTN DescriptorSize;\r
+ UINT32 PackageVersion;\r
+ CHAR16 *PackageVersionName;\r
+ UINTN Index2;\r
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;\r
+\r
+ *NoHandles = 0;\r
+ *Buffer = NULL;\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ NULL,\r
+ &NumberOfHandles,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\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
+\r
+ for (Index = 0; Index < NumberOfHandles; Index++) {\r
+ Status = gBS->HandleProtocol(\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ continue;\r
+ }\r
+\r
+ ImageInfoSize = 0;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ continue;\r
+ }\r
+\r
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\r
+ continue;\r
+ }\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
+ if (EFI_ERROR(Status)) {\r
+ FreePool(FmpImageInfoBuf);\r
+ continue;\r
+ }\r
+\r
+ if (PackageVersionName != NULL) {\r
+ FreePool(PackageVersionName);\r
+ }\r
+\r
+ TempFmpImageInfo = FmpImageInfoBuf;\r
+ for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {\r
+ //\r
+ // Check if this FMP instance matches\r
+ //\r
+ if (CompareGuid(UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {\r
+ if ((UpdateHardwareInstance == 0) ||\r
+ ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) &&\r
+ (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) {\r
+ MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];\r
+ MatchedNumberOfHandles++;\r
+ break;\r
+ }\r
+ }\r
+ TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);\r
+ }\r
+ FreePool(FmpImageInfoBuf);\r
+ }\r
+\r
+ if (MatchedNumberOfHandles == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\r
+ *NoHandles = MatchedNumberOfHandles;\r
+ *Buffer = MatchedHandleBuffer;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Return FmpImageInfoDescriptorVer by an FMP handle.\r
+\r
+ @param[in] Handle A FMP handle.\r
+\r
+ @return FmpImageInfoDescriptorVer associated with the FMP.\r
+**/\r
+UINT32\r
+GetFmpImageInfoDescriptorVer (\r
+ IN EFI_HANDLE Handle\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
+ UINT8 FmpImageInfoCount;\r
+ UINTN DescriptorSize;\r
+ UINT32 PackageVersion;\r
+ CHAR16 *PackageVersionName;\r
+\r
+ Status = gBS->HandleProtocol(\r
+ Handle,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return 0;\r
+ }\r
+\r
+ ImageInfoSize = 0;\r
+ Status = Fmp->GetImageInfo (\r
+ Fmp,\r
+ &ImageInfoSize,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return 0;\r
+ }\r
+\r
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\r
+ return 0;\r
+ }\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
+ if (EFI_ERROR(Status)) {\r
+ FreePool(FmpImageInfoBuf);\r
+ return 0;\r
+ }\r
+ return FmpImageInfoDescriptorVer;\r
+}\r
+\r
+/**\r
+ Set FMP image data.\r
+\r
+ @param[in] Handle A FMP handle.\r
+ @param[in] ImageHeader The payload image header.\r
+ @param[in] PayloadIndex The index of the payload.\r
+\r
+ @return The status of FMP->SetImage.\r
+**/\r
+EFI_STATUS\r
+SetFmpImageData (\r
+ IN EFI_HANDLE Handle,\r
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
+ IN UINTN PayloadIndex\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
+ UINT8 *Image;\r
+ VOID *VendorCode;\r
+ CHAR16 *AbortReason;\r
+\r
+ Status = gBS->HandleProtocol(\r
+ Handle,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ Image = (UINT8 *)(ImageHeader + 1);\r
+ } else {\r
+ //\r
+ // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,\r
+ // Header should exclude UpdateHardwareInstance field\r
+ //\r
+ Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
+ }\r
+\r
+ if (ImageHeader->UpdateVendorCodeSize == 0) {\r
+ VendorCode = NULL;\r
+ } else {\r
+ VendorCode = Image + ImageHeader->UpdateImageSize;\r
+ }\r
+ AbortReason = NULL;\r
+ DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));\r
+ DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));\r
+ DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ", PayloadIndex));\r
+ DEBUG((DEBUG_INFO, "ImageIndex - 0x%x ", ImageHeader->UpdateImageIndex));\r
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));\r
+ }\r
+ DEBUG((DEBUG_INFO, "\n"));\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
+ &AbortReason // AbortReason\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
+ return Status;\r
+}\r
+\r
+/**\r
+ Start a UEFI image in the FMP payload.\r
+\r
+ @param[in] ImageBuffer A pointer to the memory location containing a copy of the image to be loaded..\r
+ @param[in] ImageSize The size in bytes of ImageBuffer.\r
+\r
+ @return The status of gBS->LoadImage and gBS->StartImage.\r
+**/\r
+EFI_STATUS\r
+StartFmpImage (\r
+ IN VOID *ImageBuffer,\r
+ IN UINTN ImageSize\r
+ )\r
+{\r
+ MEMMAP_DEVICE_PATH MemMapNode;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE ImageHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
+ UINTN ExitDataSize;\r
+\r
+ SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));\r
+ MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;\r
+ MemMapNode.Header.SubType = HW_MEMMAP_DP;\r
+ MemMapNode.MemoryType = EfiBootServicesCode;\r
+ MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)ImageBuffer;\r
+ MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)ImageBuffer + ImageSize - 1);\r
+\r
+ DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);\r
+ if (DriverDevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));\r
+ Status = gBS->LoadImage(\r
+ FALSE,\r
+ gImageHandle,\r
+ DriverDevicePath,\r
+ ImageBuffer,\r
+ ImageSize,\r
+ &ImageHandle\r
+ );\r
+ DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));\r
+ if (EFI_ERROR(Status)) {\r
+ FreePool(DriverDevicePath);\r
+ return Status;\r
+ }\r
+\r
+ DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));\r
+ Status = gBS->StartImage(\r
+ ImageHandle,\r
+ &ExitDataSize,\r
+ NULL\r
+ );\r
+ DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));\r
+ if (EFI_ERROR(Status)) {\r
+ DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
+ }\r
+\r
+ FreePool(DriverDevicePath);\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Record FMP capsule status.\r
+\r
+ @param[in] Handle A FMP handle.\r
+ @param[in] CapsuleHeader The capsule image header\r
+ @param[in] CapsuleStatus The capsule process stauts\r
+ @param[in] PayloadIndex FMP payload index\r
+ @param[in] ImageHeader FMP image header\r
+**/\r
+VOID\r
+RecordFmpCapsuleStatus (\r
+ IN EFI_HANDLE Handle, OPTIONAL\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
+ IN EFI_STATUS CapsuleStatus,\r
+ IN UINTN PayloadIndex,\r
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath;\r
+ UINT32 FmpImageInfoDescriptorVer;\r
+ EFI_STATUS StatusEsrt;\r
+ ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
+ EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;\r
+\r
+ FmpDevicePath = NULL;\r
+ if (Handle != NULL) {\r
+ gBS->HandleProtocol(\r
+ Handle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **)&FmpDevicePath\r
+ );\r
+ }\r
+\r
+ RecordFmpCapsuleStatusVariable (\r
+ CapsuleHeader,\r
+ CapsuleStatus,\r
+ PayloadIndex,\r
+ ImageHeader,\r
+ FmpDevicePath\r
+ );\r
+\r
+ //\r
+ // Update corresponding ESRT entry LastAttemp Status\r
+ //\r
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
+ if (EFI_ERROR (Status)) {\r
+ return ;\r
+ }\r
+\r
+ if (Handle == NULL) {\r
+ return ;\r
+ }\r
+\r
+ //\r
+ // Update EsrtEntry For V1, V2 FMP instance.\r
+ // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface\r
+ //\r
+ FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle);\r
+ if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {\r
+ StatusEsrt = EsrtProtocol->GetEsrtEntry(&ImageHeader->UpdateImageTypeId, &EsrtEntry);\r
+ if (!EFI_ERROR(StatusEsrt)){\r
+ if (!EFI_ERROR(CapsuleStatus)) {\r
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
+ } else {\r
+ EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
+ }\r
+ EsrtEntry.LastAttemptVersion = 0;\r
+ EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);\r
+ }\r
+ }\r
+}\r
+\r
/**\r
Process Firmware management protocol data capsule.\r
\r
This function need support nested FMP capsule.\r
\r
@param[in] CapsuleHeader Points to a capsule header.\r
- @param[out] AreAllImagesProcessed If all the FMP images in the capsule are processed.\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
+ @retval EFI_NOT_READY No FMP protocol to handle this FMP capsule.\r
**/\r
EFI_STATUS\r
ProcessFmpCapsuleImage (\r
- IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
- OUT BOOLEAN *AreAllImagesProcessed\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_STATUS StatusEsrt;\r
- EFI_STATUS StatusRet;\r
EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
- UINT8 *Image;\r
- EFI_HANDLE ImageHandle;\r
UINT64 *ItemOffsetList;\r
UINT32 ItemNum;\r
UINTN Index;\r
- UINTN ExitDataSize;\r
EFI_HANDLE *HandleBuffer;\r
- EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp;\r
UINTN NumberOfHandles;\r
- UINTN DescriptorSize;\r
- UINT8 FmpImageInfoCount;\r
- UINT32 FmpImageInfoDescriptorVer;\r
- UINTN ImageInfoSize;\r
- UINT32 PackageVersion;\r
- CHAR16 *PackageVersionName;\r
- CHAR16 *AbortReason;\r
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;\r
UINTN DriverLen;\r
- UINTN Index1;\r
+ UINT64 UpdateHardwareInstance;\r
UINTN Index2;\r
- MEMMAP_DEVICE_PATH MemMapNode;\r
- EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
- EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath;\r
- ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
- EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;\r
- VOID *VendorCode;\r
+ BOOLEAN NotReady;\r
+ BOOLEAN Abort;\r
\r
if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
- return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), AreAllImagesProcessed);\r
+ return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize));\r
}\r
\r
- ASSERT(AreAllImagesProcessed != NULL);\r
-\r
- Status = EFI_SUCCESS;\r
- StatusRet = EFI_NOT_FOUND;\r
- HandleBuffer = NULL;\r
- ExitDataSize = 0;\r
- DriverDevicePath = NULL;\r
- EsrtProtocol = NULL;\r
- *AreAllImagesProcessed = FALSE;\r
+ NotReady = FALSE;\r
+ Abort = FALSE;\r
\r
DumpFmpCapsule(CapsuleHeader);\r
\r
// capsule in which driver count and payload count are both zero is not processed.\r
//\r
if (ItemNum == 0) {\r
- *AreAllImagesProcessed = TRUE;\r
return EFI_SUCCESS;\r
}\r
\r
- //\r
- // Update corresponding ESRT entry LastAttemp Status\r
- //\r
- Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
- if (EFI_ERROR (Status)) {\r
- EsrtProtocol = NULL;\r
- }\r
-\r
//\r
// 1. Try to load & start all the drivers within capsule\r
//\r
- SetDevicePathNodeLength (&MemMapNode.Header, sizeof (MemMapNode));\r
- MemMapNode.Header.Type = HARDWARE_DEVICE_PATH;\r
- MemMapNode.Header.SubType = HW_MEMMAP_DP;\r
- MemMapNode.MemoryType = EfiBootServicesCode;\r
- MemMapNode.StartingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)CapsuleHeader;\r
- MemMapNode.EndingAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)((UINT8 *)CapsuleHeader + CapsuleHeader->CapsuleImageSize - 1);\r
-\r
- DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);\r
- if (DriverDevicePath == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
-\r
for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
- if (FmpCapsuleHeader->PayloadItemCount == 0 && Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1) {\r
+ if ((FmpCapsuleHeader->PayloadItemCount == 0) &&\r
+ (Index == (UINTN)FmpCapsuleHeader->EmbeddedDriverCount - 1)) {\r
//\r
// When driver is last element in the ItemOffsetList array, the driver size is calculated by reference CapsuleImageSize in EFI_CAPSULE_HEADER\r
//\r
DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];\r
}\r
\r
- DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage ...\n"));\r
- Status = gBS->LoadImage(\r
- FALSE,\r
- gImageHandle,\r
- DriverDevicePath,\r
- (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],\r
- DriverLen,\r
- &ImageHandle\r
- );\r
- DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));\r
- if (EFI_ERROR(Status)) {\r
- StatusRet = Status;\r
- goto EXIT;\r
- }\r
-\r
- DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));\r
- Status = gBS->StartImage(\r
- ImageHandle,\r
- &ExitDataSize,\r
- NULL\r
- );\r
- DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));\r
+ Status = StartFmpImage (\r
+ (UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index],\r
+ DriverLen\r
+ );\r
if (EFI_ERROR(Status)) {\r
DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
- StatusRet = Status;\r
- goto EXIT;\r
+ return Status;\r
}\r
}\r
\r
//\r
DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));\r
\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
- &gEfiFirmwareManagementProtocolGuid,\r
- NULL,\r
- &NumberOfHandles,\r
- &HandleBuffer\r
- );\r
-\r
- if (!EFI_ERROR(Status)) {\r
- for(Index1 = 0; Index1 < NumberOfHandles; Index1++) {\r
- Status = gBS->HandleProtocol(\r
- HandleBuffer[Index1],\r
- &gEfiFirmwareManagementProtocolGuid,\r
- (VOID **)&Fmp\r
- );\r
- if (EFI_ERROR(Status)) {\r
- continue;\r
- }\r
-\r
- FmpDevicePath = NULL;\r
- gBS->HandleProtocol(\r
- HandleBuffer[Index1],\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **)&FmpDevicePath\r
- );\r
+ DumpAllFmpInfo ();\r
\r
- ImageInfoSize = 0;\r
- Status = Fmp->GetImageInfo (\r
- Fmp,\r
- &ImageInfoSize,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL,\r
- NULL\r
- );\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- continue;\r
- }\r
+ //\r
+ // Check all the payload entry in capsule payload list\r
+ //\r
+ for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
+ ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
\r
- FmpImageInfoBuf = NULL;\r
- FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
- if (FmpImageInfoBuf == NULL) {\r
- StatusRet = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
+ UpdateHardwareInstance = 0;\r
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;\r
+ }\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
+ Status = GetFmpHandleBufferByType (\r
+ &ImageHeader->UpdateImageTypeId,\r
+ UpdateHardwareInstance,\r
+ &NumberOfHandles,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ NotReady = TRUE;\r
+ RecordFmpCapsuleStatus (\r
+ NULL,\r
+ CapsuleHeader,\r
+ EFI_NOT_READY,\r
+ Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
+ ImageHeader\r
+ );\r
+ continue;\r
+ }\r
\r
- //\r
- // If FMP GetInformation interface failed, skip this resource\r
- //\r
- if (EFI_ERROR(Status)) {\r
- FreePool(FmpImageInfoBuf);\r
+ for (Index2 = 0; Index2 < NumberOfHandles; Index2++) {\r
+ if (Abort) {\r
+ RecordFmpCapsuleStatus (\r
+ HandleBuffer[Index2],\r
+ CapsuleHeader,\r
+ EFI_ABORTED,\r
+ Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
+ ImageHeader\r
+ );\r
continue;\r
}\r
\r
- DEBUG((DEBUG_INFO, "FMP (%d) ImageInfo:\n", Index));\r
- DumpFmpImageInfo(\r
- ImageInfoSize, // ImageInfoSize\r
- FmpImageInfoBuf, // ImageInfo\r
- FmpImageInfoDescriptorVer, // DescriptorVersion\r
- FmpImageInfoCount, // DescriptorCount\r
- DescriptorSize, // DescriptorSize\r
- PackageVersion, // PackageVersion\r
- PackageVersionName // PackageVersionName\r
- );\r
-\r
- if (PackageVersionName != NULL) {\r
- FreePool(PackageVersionName);\r
+ Status = SetFmpImageData (\r
+ HandleBuffer[Index2],\r
+ ImageHeader,\r
+ Index - FmpCapsuleHeader->EmbeddedDriverCount\r
+ );\r
+ if (Status != EFI_SUCCESS) {\r
+ Abort = TRUE;\r
}\r
\r
- TempFmpImageInfo = FmpImageInfoBuf;\r
- for (Index2 = 0; Index2 < FmpImageInfoCount; Index2++) {\r
- //\r
- // Check all the payload entry in capsule payload list\r
- //\r
- for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
- ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
-\r
- if (IsFmpCapsuleProcessed(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {\r
- DEBUG((DEBUG_INFO, "FMP Capsule already processed (%g):", CapsuleHeader));\r
- DEBUG((DEBUG_INFO, "ImageTypeId - %g, ", &ImageHeader->UpdateImageTypeId));\r
- DEBUG((DEBUG_INFO, "PayloadIndex - 0x%x, ImageIndex - 0x%x\n", Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader->UpdateImageIndex));\r
- continue;\r
- }\r
-\r
- if (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId)) {\r
- AbortReason = NULL;\r
- if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
- if(ImageHeader->UpdateHardwareInstance != 0){\r
- //\r
- // FMP Version is >=2 & UpdateHardwareInstance Skip 2 case\r
- // 1. FMP Image info Version < 3\r
- // 2. HardwareInstance doesn't match\r
- //\r
- if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION ||\r
- ImageHeader->UpdateHardwareInstance != TempFmpImageInfo->HardwareInstance) {\r
- continue;\r
- }\r
- }\r
- Image = (UINT8 *)(ImageHeader + 1);\r
- } else {\r
- //\r
- // If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1, only match ImageTypeId.\r
- // Header should exclude UpdateHardwareInstance field\r
- //\r
- Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
- }\r
-\r
- if (ImageHeader->UpdateVendorCodeSize == 0) {\r
- VendorCode = NULL;\r
- } else {\r
- VendorCode = Image + ImageHeader->UpdateImageSize;\r
- }\r
- DEBUG((DEBUG_INFO, "Fmp->SetImage ...\n"));\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
- &AbortReason // AbortReason\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
- RecordFmpCapsuleStatusVariable(\r
- CapsuleHeader, // CapsuleGuid\r
- Status, // CapsuleStatus\r
- Index - FmpCapsuleHeader->EmbeddedDriverCount, // PayloadIndex\r
- ImageHeader, // ImageHeader\r
- FmpDevicePath // FmpDevicePath\r
- );\r
- if (StatusRet != EFI_SUCCESS) {\r
- StatusRet = Status;\r
- }\r
- //\r
- // Update EsrtEntry For V1, V2 FMP instance. V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface\r
- //\r
- if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION && EsrtProtocol != NULL) {\r
- StatusEsrt = EsrtProtocol->GetEsrtEntry(&TempFmpImageInfo->ImageTypeId, &EsrtEntry);\r
- if (!EFI_ERROR(StatusEsrt)){\r
- if (!EFI_ERROR(Status)) {\r
- EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_SUCCESS;\r
- } else {\r
- EsrtEntry.LastAttemptStatus = LAST_ATTEMPT_STATUS_ERROR_UNSUCCESSFUL;\r
- }\r
- EsrtEntry.LastAttemptVersion = 0;\r
- EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);\r
- }\r
- }\r
- }\r
- }\r
- //\r
- // Use DescriptorSize to move ImageInfo Pointer to stay compatible with different ImageInfo version\r
- //\r
- TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);\r
- }\r
- FreePool(FmpImageInfoBuf);\r
+ RecordFmpCapsuleStatus (\r
+ HandleBuffer[Index2],\r
+ CapsuleHeader,\r
+ Status,\r
+ Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
+ ImageHeader\r
+ );\r
}\r
- }\r
-\r
- //\r
- // final check for AreAllImagesProcessed\r
- //\r
- *AreAllImagesProcessed = TRUE;\r
- for (Index = FmpCapsuleHeader->EmbeddedDriverCount; Index < ItemNum; Index++) {\r
- ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
-\r
- if (!IsFmpCapsuleProcessed(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {\r
- *AreAllImagesProcessed = FALSE;\r
- break;\r
+ if (HandleBuffer != NULL) {\r
+ FreePool(HandleBuffer);\r
}\r
}\r
\r
-EXIT:\r
-\r
- if (HandleBuffer != NULL) {\r
- FreePool(HandleBuffer);\r
- }\r
-\r
- if (DriverDevicePath != NULL) {\r
- FreePool(DriverDevicePath);\r
+ if (NotReady) {\r
+ return EFI_NOT_READY;\r
}\r
\r
- return StatusRet;\r
+ //\r
+ // always return SUCCESS to indicate this capsule is processed.\r
+ // The status of SetImage is recorded in capsule result variable.\r
+ //\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
)\r
{\r
EFI_STATUS Status;\r
- BOOLEAN AreAllImagesProcessed;\r
\r
if (SupportCapsuleImage (CapsuleHeader) != EFI_SUCCESS) {\r
+ RecordCapsuleStatusVariable(CapsuleHeader, EFI_UNSUPPORTED);\r
return EFI_UNSUPPORTED;\r
}\r
\r
Status = ValidateFmpCapsule(CapsuleHeader, NULL);\r
DEBUG((DEBUG_INFO, "ValidateFmpCapsule - %r\n", Status));\r
if (EFI_ERROR(Status)) {\r
+ RecordCapsuleStatusVariable(CapsuleHeader, Status);\r
return Status;\r
}\r
\r
// Press EFI FMP Capsule\r
//\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));\r
- Status = ProcessFmpCapsuleImage(CapsuleHeader, &AreAllImagesProcessed);\r
+ Status = ProcessFmpCapsuleImage(CapsuleHeader);\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));\r
\r
- if (!AreAllImagesProcessed) {\r
- mAreAllImagesProcessed = FALSE;\r
- }\r
-\r
return Status;\r
}\r
\r
);\r
\r
extern BOOLEAN mDxeCapsuleLibEndOfDxe;\r
-extern BOOLEAN mAreAllImagesProcessed;\r
BOOLEAN mNeedReset;\r
\r
-/**\r
-\r
- This routine is called to process capsules.\r
-\r
- Caution: This function may receive untrusted input.\r
-\r
- Each individual capsule result is recorded in capsule record variable.\r
-\r
- @param[in] NeedBlockDriver TRUE: Need skip the FMP capsules with non zero EmbeddedDriverCount.\r
- FALSE: No need to skip any FMP capsules.\r
-\r
- @retval EFI_SUCCESS There is no error when processing capsules.\r
- @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.\r
+VOID **mCapsulePtr;\r
+EFI_STATUS *mCapsuleStatusArray;\r
+UINT32 mCapsuleTotalNumber;\r
\r
+/**\r
+ This function initializes the mCapsulePtr, mCapsuleStatusArray and mCapsuleTotalNumber.\r
**/\r
-EFI_STATUS\r
-ProcessTheseCapsules (\r
- IN BOOLEAN NeedBlockDriver\r
+VOID\r
+InitCapsulePtr (\r
+ VOID\r
)\r
{\r
- EFI_STATUS Status;\r
EFI_PEI_HOB_POINTERS HobPointer;\r
- EFI_CAPSULE_HEADER *CapsuleHeader;\r
- UINT32 Size;\r
- UINT32 CapsuleNumber;\r
- UINT32 CapsuleTotalNumber;\r
- EFI_CAPSULE_TABLE *CapsuleTable;\r
- UINT32 Index;\r
- UINT32 CacheIndex;\r
- UINT32 CacheNumber;\r
- VOID **CapsulePtr;\r
- VOID **CapsulePtrCache;\r
- EFI_GUID *CapsuleGuidCache;\r
- EFI_STATUS *CapsuleStatusArray;\r
- BOOLEAN DisplayCapsuleExist;\r
- ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;\r
- UINT16 EmbeddedDriverCount;\r
-\r
- REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));\r
+ UINTN Index;\r
\r
- CapsuleNumber = 0;\r
- CapsuleTotalNumber = 0;\r
- CacheIndex = 0;\r
- CacheNumber = 0;\r
- CapsulePtr = NULL;\r
- CapsulePtrCache = NULL;\r
- CapsuleGuidCache = NULL;\r
- DisplayCapsuleExist = FALSE;\r
- EsrtManagement = NULL;\r
-\r
- Status = EFI_SUCCESS;\r
//\r
// Find all capsule images from hob\r
//\r
if (!IsValidCapsuleHeader((VOID *)(UINTN)HobPointer.Capsule->BaseAddress, HobPointer.Capsule->Length)) {\r
HobPointer.Header->HobType = EFI_HOB_TYPE_UNUSED; // Mark this hob as invalid\r
} else {\r
- CapsuleTotalNumber++;\r
+ mCapsuleTotalNumber++;\r
}\r
HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
}\r
\r
- if (CapsuleTotalNumber == 0) {\r
- //\r
- // We didn't find a hob, so had no errors.\r
- //\r
- DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update boot mode.\n"));\r
- Status = EFI_SUCCESS;\r
- goto Done;\r
+ DEBUG ((DEBUG_INFO, "mCapsuleTotalNumber - 0x%x\n", mCapsuleTotalNumber));\r
+\r
+ if (mCapsuleTotalNumber == 0) {\r
+ return ;\r
}\r
\r
//\r
// Init temp Capsule Data table.\r
//\r
- CapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
- ASSERT (CapsulePtr != NULL);\r
- if (CapsulePtr == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
- CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * CapsuleTotalNumber);\r
- ASSERT (CapsulePtrCache != NULL);\r
- if (CapsulePtrCache == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
+ mCapsulePtr = (VOID **) AllocateZeroPool (sizeof (VOID *) * mCapsuleTotalNumber);\r
+ if (mCapsulePtr == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Allocate mCapsulePtr fail!\n"));\r
+ mCapsuleTotalNumber = 0;\r
+ return ;\r
}\r
- CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * CapsuleTotalNumber);\r
- ASSERT (CapsuleGuidCache != NULL);\r
- if (CapsuleGuidCache == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
- }\r
- CapsuleStatusArray = (EFI_STATUS *) AllocateZeroPool (sizeof (EFI_STATUS) * CapsuleTotalNumber);\r
- ASSERT (CapsuleStatusArray != NULL);\r
- if (CapsuleStatusArray == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Done;\r
+ mCapsuleStatusArray = (EFI_STATUS *) AllocateZeroPool (sizeof (EFI_STATUS) * mCapsuleTotalNumber);\r
+ if (mCapsuleStatusArray == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Allocate mCapsuleStatusArray fail!\n"));\r
+ FreePool (mCapsulePtr);\r
+ mCapsulePtr = NULL;\r
+ mCapsuleTotalNumber = 0;\r
+ return ;\r
}\r
+ SetMemN (mCapsuleStatusArray, sizeof (EFI_STATUS) * mCapsuleTotalNumber, EFI_NOT_READY);\r
\r
//\r
// Find all capsule images from hob\r
//\r
HobPointer.Raw = GetHobList ();\r
+ Index = 0;\r
while ((HobPointer.Raw = GetNextHob (EFI_HOB_TYPE_UEFI_CAPSULE, HobPointer.Raw)) != NULL) {\r
- CapsulePtr [CapsuleNumber++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;\r
+ mCapsulePtr [Index++] = (VOID *) (UINTN) HobPointer.Capsule->BaseAddress;\r
HobPointer.Raw = GET_NEXT_HOB (HobPointer);\r
}\r
+}\r
\r
- //\r
- // Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
- // capsuleTable to configure table with EFI_CAPSULE_GUID\r
- //\r
+/**\r
+ This function returns if all capsule images are processed.\r
+\r
+ @retval TRUE All capsule images are processed.\r
+ @retval FALSE Not all capsule images are processed.\r
+**/\r
+BOOLEAN\r
+AreAllImagesProcessed (\r
+ VOID\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
+ if (mCapsuleStatusArray[Index] == EFI_NOT_READY) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ This function populates capsule in the configuration table.\r
+**/\r
+VOID\r
+PopulateCapsuleInConfigurationTable (\r
+ VOID\r
+ )\r
+{\r
+ VOID **CapsulePtrCache;\r
+ EFI_GUID *CapsuleGuidCache;\r
+ EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ EFI_CAPSULE_TABLE *CapsuleTable;\r
+ UINT32 CacheIndex;\r
+ UINT32 CacheNumber;\r
+ UINT32 CapsuleNumber;\r
+ UINTN Index;\r
+ UINTN Size;\r
+ EFI_STATUS Status;\r
+\r
+ if (mCapsuleTotalNumber == 0) {\r
+ return ;\r
+ }\r
+\r
+ CapsulePtrCache = NULL;\r
+ CapsuleGuidCache = NULL;\r
+ CacheIndex = 0;\r
+ CacheNumber = 0;\r
+\r
+ CapsulePtrCache = (VOID **) AllocateZeroPool (sizeof (VOID *) * mCapsuleTotalNumber);\r
+ if (CapsulePtrCache == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Allocate CapsulePtrCache fail!\n"));\r
+ return ;\r
+ }\r
+ CapsuleGuidCache = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID) * mCapsuleTotalNumber);\r
+ if (CapsuleGuidCache == NULL) {\r
+ DEBUG ((DEBUG_ERROR, "Allocate CapsuleGuidCache fail!\n"));\r
+ FreePool (CapsulePtrCache);\r
+ return ;\r
+ }\r
\r
//\r
// Capsules who have CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE always are used for operating\r
// Firstly, Loop for all coalesced capsules, record unique CapsuleGuids and cache them in an\r
// array for later sorting capsules by CapsuleGuid.\r
//\r
- for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
- CapsuleStatusArray [Index] = EFI_UNSUPPORTED;\r
- CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
//\r
// For each capsule, we compare it with known CapsuleGuid in the CacheArray.\r
// will look in EFI System Table and search for the capsule's Guid and associated\r
// pointer to retrieve the data.\r
//\r
- CacheIndex = 0;\r
- while (CacheIndex < CacheNumber) {\r
+ for (CacheIndex = 0; CacheIndex < CacheNumber; CacheIndex++) {\r
CapsuleNumber = 0;\r
- for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
- CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
+ for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
if ((CapsuleHeader->Flags & CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE) != 0) {\r
if (CompareGuid (&CapsuleGuidCache[CacheIndex], &CapsuleHeader->CapsuleGuid)) {\r
//\r
// Cache Caspuleheader to the array, this array is uniqued with certain CapsuleGuid.\r
//\r
CapsulePtrCache[CapsuleNumber++] = (VOID*)CapsuleHeader;\r
- //\r
- // When a Capsule is listed in CapsulePtrCache, it will be reported in ConfigurationTable\r
- // So, report the CapsuleStatus as "processed successfully".\r
- //\r
- CapsuleStatusArray [Index] = EFI_SUCCESS;\r
}\r
}\r
}\r
if (CapsuleNumber != 0) {\r
Size = sizeof(EFI_CAPSULE_TABLE) + (CapsuleNumber - 1) * sizeof(VOID*);\r
CapsuleTable = AllocateRuntimePool (Size);\r
- ASSERT (CapsuleTable != NULL);\r
if (CapsuleTable == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
+ DEBUG ((DEBUG_ERROR, "Allocate CapsuleTable (%g) fail!\n", &CapsuleGuidCache[CacheIndex]));\r
+ continue;\r
}\r
CapsuleTable->CapsuleArrayNumber = CapsuleNumber;\r
CopyMem(&CapsuleTable->CapsulePtr[0], CapsulePtrCache, CapsuleNumber * sizeof(VOID*));\r
Status = gBS->InstallConfigurationTable (&CapsuleGuidCache[CacheIndex], (VOID*)CapsuleTable);\r
- ASSERT_EFI_ERROR (Status);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((DEBUG_ERROR, "InstallConfigurationTable (%g) fail!\n", &CapsuleGuidCache[CacheIndex]));\r
+ }\r
}\r
- CacheIndex++;\r
+ }\r
+\r
+ FreePool(CapsuleGuidCache);\r
+ FreePool(CapsulePtrCache);\r
+}\r
+\r
+/**\r
+\r
+ This routine is called to process capsules.\r
+\r
+ Caution: This function may receive untrusted input.\r
+\r
+ Each individual capsule result is recorded in capsule record variable.\r
+\r
+ @param[in] FirstRound TRUE: First round. Need skip the FMP capsules with non zero EmbeddedDriverCount.\r
+ FALSE: Process rest FMP capsules.\r
+\r
+ @retval EFI_SUCCESS There is no error when processing capsules.\r
+ @retval EFI_OUT_OF_RESOURCES No enough resource to process capsules.\r
+\r
+**/\r
+EFI_STATUS\r
+ProcessTheseCapsules (\r
+ IN BOOLEAN FirstRound\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_CAPSULE_HEADER *CapsuleHeader;\r
+ UINT32 Index;\r
+ BOOLEAN DisplayCapsuleExist;\r
+ ESRT_MANAGEMENT_PROTOCOL *EsrtManagement;\r
+ UINT16 EmbeddedDriverCount;\r
+\r
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin)));\r
+\r
+ if (FirstRound) {\r
+ InitCapsulePtr ();\r
+ }\r
+\r
+ if (mCapsuleTotalNumber == 0) {\r
+ //\r
+ // We didn't find a hob, so had no errors.\r
+ //\r
+ DEBUG ((DEBUG_ERROR, "We can not find capsule data in capsule update boot mode.\n"));\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ if (AreAllImagesProcessed ()) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Check the capsule flags,if contains CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE, install\r
+ // capsuleTable to configure table with EFI_CAPSULE_GUID\r
+ //\r
+ if (FirstRound) {\r
+ PopulateCapsuleInConfigurationTable ();\r
}\r
\r
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdatingFirmware)));\r
//\r
// If Windows UX capsule exist, process it first\r
//\r
- for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
- CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
- if (CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {\r
+ DisplayCapsuleExist = FALSE;\r
+ for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
+ if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
DEBUG ((DEBUG_INFO, "ProcessCapsuleImage (Ux) - 0x%x\n", CapsuleHeader));\r
DisplayCapsuleExist = TRUE;\r
DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n"));\r
Status = ProcessCapsuleImage (CapsuleHeader);\r
+ mCapsuleStatusArray [Index] = EFI_SUCCESS;\r
DEBUG((DEBUG_INFO, "ProcessCapsuleImage (Ux) - %r\n", Status));\r
- CapsuleStatusArray [Index] = Status;\r
break;\r
}\r
}\r
//\r
// All capsules left are recognized by platform.\r
//\r
- for (Index = 0; Index < CapsuleTotalNumber; Index++) {\r
- CapsuleHeader = (EFI_CAPSULE_HEADER*) CapsulePtr [Index];\r
- if (!CompareGuid(&CapsuleHeader->CapsuleGuid ,&gWindowsUxCapsuleGuid)) {\r
+ for (Index = 0; Index < mCapsuleTotalNumber; Index++) {\r
+ if (mCapsuleStatusArray [Index] != EFI_NOT_READY) {\r
+ // already processed\r
+ continue;\r
+ }\r
+ CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index];\r
+ if (!CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) {\r
//\r
// Call capsule library to process capsule image.\r
//\r
EmbeddedDriverCount = 0;\r
if (IsFmpCapsule(CapsuleHeader)) {\r
- Status = ValidateFmpCapsule(CapsuleHeader, &EmbeddedDriverCount);\r
+ Status = ValidateFmpCapsule (CapsuleHeader, &EmbeddedDriverCount);\r
if (EFI_ERROR(Status)) {\r
DEBUG((DEBUG_ERROR, "ValidateFmpCapsule failed. Ignore!\n"));\r
+ mCapsuleStatusArray [Index] = EFI_ABORTED;\r
continue;\r
}\r
+ } else {\r
+ mCapsuleStatusArray [Index] = EFI_ABORTED;\r
+ continue;\r
}\r
\r
- if ((!NeedBlockDriver) || (EmbeddedDriverCount == 0)) {\r
+ if ((!FirstRound) || (EmbeddedDriverCount == 0)) {\r
DEBUG((DEBUG_INFO, "ProcessCapsuleImage - 0x%x\n", CapsuleHeader));\r
Status = ProcessCapsuleImage (CapsuleHeader);\r
- CapsuleStatusArray [Index] = Status;\r
+ mCapsuleStatusArray [Index] = Status;\r
DEBUG((DEBUG_INFO, "ProcessCapsuleImage - %r\n", Status));\r
\r
- if (EFI_ERROR(Status)) {\r
- REPORT_STATUS_CODE(EFI_ERROR_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareFailed)));\r
- DEBUG ((DEBUG_ERROR, "Capsule process failed. reset the system!\n"));\r
- Print (L"Firmware update failed...\r\n");\r
- } else {\r
- REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareSuccess)));\r
- }\r
-\r
- if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 ||\r
- IsFmpCapsule(CapsuleHeader)) {\r
- mNeedReset = TRUE;\r
+ if (Status != EFI_NOT_READY) {\r
+ if (EFI_ERROR(Status)) {\r
+ REPORT_STATUS_CODE(EFI_ERROR_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareFailed)));\r
+ DEBUG ((DEBUG_ERROR, "Capsule process failed!\n"));\r
+ Print (L"Firmware update failed...\r\n");\r
+ } else {\r
+ REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareSuccess)));\r
+ }\r
+\r
+ if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 ||\r
+ IsFmpCapsule(CapsuleHeader)) {\r
+ mNeedReset = TRUE;\r
+ }\r
}\r
}\r
}\r
}\r
Status = EFI_SUCCESS;\r
\r
-Done:\r
- //\r
- // Free the allocated temp memory space.\r
- //\r
- if (CapsuleGuidCache != NULL) {\r
- FreePool(CapsuleGuidCache);\r
- }\r
- if (CapsulePtrCache != NULL) {\r
- FreePool(CapsulePtrCache);\r
- }\r
- if (CapsulePtr != NULL) {\r
- FreePool(CapsulePtr);\r
- }\r
-\r
REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesEnd)));\r
\r
return Status;\r
EFI_STATUS Status;\r
\r
if (!mDxeCapsuleLibEndOfDxe) {\r
- //\r
- // Initialize mAreAllImagesProcessed to be TRUE.\r
- //\r
- // It will be updated to FALSE in ProcessTheseCapsules()->ProcessCapsuleImage(),\r
- // if there is any FMP image in any FMP capsule not processed.\r
- //\r
- mAreAllImagesProcessed = TRUE;\r
-\r
Status = ProcessTheseCapsules(TRUE);\r
+\r
//\r
// Reboot System if and only if all capsule processed.\r
// If not, defer reset to 2nd process.\r
//\r
- if (mNeedReset && mAreAllImagesProcessed) {\r
+ if (mNeedReset && AreAllImagesProcessed()) {\r
DoResetSystem();\r
}\r
} else {\r