buffer overflow, integer overflow.\r
\r
SupportCapsuleImage(), ProcessCapsuleImage(), IsValidCapsuleHeader(),\r
- ValidateFmpCapsule(), DisplayCapsuleImage(), ConvertBmpToGopBlt() will\r
- receive untrusted input and do basic validation.\r
+ ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and\r
+ performs 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
#include <PiDxe.h>\r
\r
-#include <IndustryStandard/Bmp.h>\r
#include <IndustryStandard/WindowsUxCapsule.h>\r
\r
#include <Guid/FmpCapsule.h>\r
#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
-BOOLEAN mAreAllImagesProcessed;\r
+EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;\r
+BOOLEAN mIsVirtualAddrConverted = FALSE;\r
+\r
+BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;\r
+EFI_EVENT mDxeCapsuleLibEndOfDxeEvent = NULL;\r
\r
-EFI_SYSTEM_RESOURCE_TABLE *mEsrtTable = NULL;\r
-BOOLEAN mIsVirtualAddrConverted = FALSE;\r
-BOOLEAN mDxeCapsuleLibEndOfDxe = FALSE;\r
+EDKII_FIRMWARE_MANAGEMENT_PROGRESS_PROTOCOL *mFmpProgress = NULL;\r
\r
/**\r
Initialize capsule related variables.\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
@param[in] CapsuleStatus The capsule process stauts\r
@param[in] PayloadIndex FMP payload index\r
@param[in] ImageHeader FMP image header\r
+ @param[in] FmpDevicePath DevicePath associated with the FMP producer\r
\r
@retval EFI_SUCCESS The capsule status variable is recorded.\r
@retval EFI_OUT_OF_RESOURCES No resource to record the capsule status variable.\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
+ IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL\r
);\r
\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
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Convert a *.BMP graphics image to a GOP blt buffer. If a NULL Blt buffer\r
- is passed in a GopBlt buffer will be allocated by this routine. If a GopBlt\r
- buffer is passed in it will be used if it is big enough.\r
-\r
- Caution: This function may receive untrusted input.\r
-\r
- @param[in] BmpImage Pointer to BMP file\r
- @param[in] BmpImageSize Number of bytes in BmpImage\r
- @param[in, out] GopBlt Buffer containing GOP version of BmpImage.\r
- @param[in, out] GopBltSize Size of GopBlt in bytes.\r
- @param[out] PixelHeight Height of GopBlt/BmpImage in pixels\r
- @param[out] PixelWidth Width of GopBlt/BmpImage in pixels\r
-\r
- @retval EFI_SUCCESS GopBlt and GopBltSize are returned.\r
- @retval EFI_UNSUPPORTED BmpImage is not a valid *.BMP image\r
- @retval EFI_BUFFER_TOO_SMALL The passed in GopBlt buffer is not big enough.\r
- GopBltSize will contain the required size.\r
- @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-ConvertBmpToGopBlt (\r
- IN VOID *BmpImage,\r
- IN UINTN BmpImageSize,\r
- IN OUT VOID **GopBlt,\r
- IN OUT UINTN *GopBltSize,\r
- OUT UINTN *PixelHeight,\r
- OUT UINTN *PixelWidth\r
- )\r
-{\r
- UINT8 *Image;\r
- UINT8 *ImageHeader;\r
- BMP_IMAGE_HEADER *BmpHeader;\r
- BMP_COLOR_MAP *BmpColorMap;\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;\r
- EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;\r
- UINT64 BltBufferSize;\r
- UINTN Index;\r
- UINTN Height;\r
- UINTN Width;\r
- UINTN ImageIndex;\r
- UINT32 DataSizePerLine;\r
- BOOLEAN IsAllocated;\r
- UINT32 ColorMapNum;\r
-\r
- if (sizeof (BMP_IMAGE_HEADER) > BmpImageSize) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- BmpHeader = (BMP_IMAGE_HEADER *) BmpImage;\r
-\r
- if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Doesn't support compress.\r
- //\r
- if (BmpHeader->CompressionType != 0) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // Only support BITMAPINFOHEADER format.\r
- // BITMAPFILEHEADER + BITMAPINFOHEADER = BMP_IMAGE_HEADER\r
- //\r
- if (BmpHeader->HeaderSize != sizeof (BMP_IMAGE_HEADER) - OFFSET_OF(BMP_IMAGE_HEADER, HeaderSize)) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- //\r
- // The data size in each line must be 4 byte alignment.\r
- //\r
- DataSizePerLine = ((BmpHeader->PixelWidth * BmpHeader->BitPerPixel + 31) >> 3) & (~0x3);\r
- BltBufferSize = MultU64x32 (DataSizePerLine, BmpHeader->PixelHeight);\r
- if (BltBufferSize > (UINT32) ~0) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if ((BmpHeader->Size != BmpImageSize) ||\r
- (BmpHeader->Size < BmpHeader->ImageOffset) ||\r
- (BmpHeader->Size - BmpHeader->ImageOffset != BmpHeader->PixelHeight * DataSizePerLine)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- //\r
- // Calculate Color Map offset in the image.\r
- //\r
- Image = BmpImage;\r
- BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER));\r
- if (BmpHeader->ImageOffset < sizeof (BMP_IMAGE_HEADER)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (BmpHeader->ImageOffset > sizeof (BMP_IMAGE_HEADER)) {\r
- switch (BmpHeader->BitPerPixel) {\r
- case 1:\r
- ColorMapNum = 2;\r
- break;\r
- case 4:\r
- ColorMapNum = 16;\r
- break;\r
- case 8:\r
- ColorMapNum = 256;\r
- break;\r
- default:\r
- ColorMapNum = 0;\r
- break;\r
- }\r
- //\r
- // BMP file may has padding data between the bmp header section and the bmp data section.\r
- //\r
- if (BmpHeader->ImageOffset - sizeof (BMP_IMAGE_HEADER) < sizeof (BMP_COLOR_MAP) * ColorMapNum) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- //\r
- // Calculate graphics image data address in the image\r
- //\r
- Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset;\r
- ImageHeader = Image;\r
-\r
- //\r
- // Calculate the BltBuffer needed size.\r
- //\r
- BltBufferSize = MultU64x32 ((UINT64) BmpHeader->PixelWidth, BmpHeader->PixelHeight);\r
- //\r
- // Ensure the BltBufferSize * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) doesn't overflow\r
- //\r
- if (BltBufferSize > DivU64x32 ((UINTN) ~0, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))) {\r
- return EFI_UNSUPPORTED;\r
- }\r
- BltBufferSize = MultU64x32 (BltBufferSize, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL));\r
-\r
- IsAllocated = FALSE;\r
- if (*GopBlt == NULL) {\r
- //\r
- // GopBlt is not allocated by caller.\r
- //\r
- *GopBltSize = (UINTN) BltBufferSize;\r
- *GopBlt = AllocatePool (*GopBltSize);\r
- IsAllocated = TRUE;\r
- if (*GopBlt == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- //\r
- // GopBlt has been allocated by caller.\r
- //\r
- if (*GopBltSize < (UINTN) BltBufferSize) {\r
- *GopBltSize = (UINTN) BltBufferSize;\r
- return EFI_BUFFER_TOO_SMALL;\r
- }\r
- }\r
-\r
- *PixelWidth = BmpHeader->PixelWidth;\r
- *PixelHeight = BmpHeader->PixelHeight;\r
-\r
- //\r
- // Convert image from BMP to Blt buffer format\r
- //\r
- BltBuffer = *GopBlt;\r
- for (Height = 0; Height < BmpHeader->PixelHeight; Height++) {\r
- Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth];\r
- for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) {\r
- switch (BmpHeader->BitPerPixel) {\r
- case 1:\r
- //\r
- // Convert 1-bit (2 colors) BMP to 24-bit color\r
- //\r
- for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) {\r
- Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red;\r
- Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green;\r
- Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue;\r
- Blt++;\r
- Width++;\r
- }\r
-\r
- Blt--;\r
- Width--;\r
- break;\r
-\r
- case 4:\r
- //\r
- // Convert 4-bit (16 colors) BMP Palette to 24-bit color\r
- //\r
- Index = (*Image) >> 4;\r
- Blt->Red = BmpColorMap[Index].Red;\r
- Blt->Green = BmpColorMap[Index].Green;\r
- Blt->Blue = BmpColorMap[Index].Blue;\r
- if (Width < (BmpHeader->PixelWidth - 1)) {\r
- Blt++;\r
- Width++;\r
- Index = (*Image) & 0x0f;\r
- Blt->Red = BmpColorMap[Index].Red;\r
- Blt->Green = BmpColorMap[Index].Green;\r
- Blt->Blue = BmpColorMap[Index].Blue;\r
- }\r
- break;\r
-\r
- case 8:\r
- //\r
- // Convert 8-bit (256 colors) BMP Palette to 24-bit color\r
- //\r
- Blt->Red = BmpColorMap[*Image].Red;\r
- Blt->Green = BmpColorMap[*Image].Green;\r
- Blt->Blue = BmpColorMap[*Image].Blue;\r
- break;\r
-\r
- case 24:\r
- //\r
- // It is 24-bit BMP.\r
- //\r
- Blt->Blue = *Image++;\r
- Blt->Green = *Image++;\r
- Blt->Red = *Image;\r
- break;\r
-\r
- case 32:\r
- //\r
- // it is 32-bit BMP. Skip pixel's highest byte\r
- //\r
- Blt->Blue = *Image++;\r
- Blt->Green = *Image++;\r
- Blt->Red = *Image++;\r
- break;\r
-\r
- default:\r
- //\r
- // Other bit format BMP is not supported.\r
- //\r
- if (IsAllocated) {\r
- FreePool (*GopBlt);\r
- *GopBlt = NULL;\r
- }\r
- return EFI_UNSUPPORTED;\r
- };\r
-\r
- }\r
-\r
- ImageIndex = (UINTN) (Image - ImageHeader);\r
- if ((ImageIndex % 4) != 0) {\r
- //\r
- // Bmp Image starts each row on a 32-bit boundary!\r
- //\r
- Image = Image + (4 - (ImageIndex % 4));\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-\r
/**\r
Those capsules supported by the firmwares.\r
\r
UINTN Width;\r
EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
\r
- ImagePayload = (DISPLAY_DISPLAY_PAYLOAD *)(CapsuleHeader + 1);\r
- PayloadSize = (UINTN)(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
Blt = NULL;\r
Width = 0;\r
Height = 0;\r
- Status = ConvertBmpToGopBlt (\r
+ Status = TranslateBmpToGopBlt (\r
ImagePayload + 1,\r
PayloadSize - sizeof(DISPLAY_DISPLAY_PAYLOAD),\r
- (VOID **)&Blt,\r
+ &Blt,\r
&BltSize,\r
&Height,\r
&Width\r
for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));\r
}\r
- for (; Index < (UINTN)(FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount); Index++) {\r
+ for (; Index < (UINT32)FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount; Index++) {\r
DEBUG((DEBUG_VERBOSE, " ItemOffsetList[%d] - 0x%lx\n", Index, ItemOffsetList[Index]));\r
ImageHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *)((UINT8 *)FmpCapsuleHeader + ItemOffsetList[Index]);\r
\r
}\r
\r
/**\r
- Process Firmware management protocol data capsule.\r
-\r
- This function assumes the caller validated the capsule by using\r
- ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,\r
- EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and\r
- EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.\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
+ Dump all FMP information.\r
**/\r
-EFI_STATUS\r
-ProcessFmpCapsuleImage (\r
- IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
- OUT BOOLEAN *AreAllImagesProcessed\r
+VOID\r
+DumpAllFmpInfo (\r
+ VOID\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
+ 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
- CHAR16 *AbortReason;\r
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *FmpImageInfoBuf;\r
- EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo;\r
- UINTN DriverLen;\r
- UINTN Index1;\r
- UINTN Index2;\r
- MEMMAP_DEVICE_PATH MemMapNode;\r
- EFI_DEVICE_PATH_PROTOCOL *DriverDevicePath;\r
- ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol;\r
- EFI_SYSTEM_RESOURCE_ENTRY EsrtEntry;\r
- VOID *VendorCode;\r
\r
- if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
- return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), AreAllImagesProcessed);\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
- ASSERT(AreAllImagesProcessed != NULL);\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
- Status = EFI_SUCCESS;\r
- StatusRet = EFI_NOT_FOUND;\r
- HandleBuffer = NULL;\r
- ExitDataSize = 0;\r
- DriverDevicePath = NULL;\r
- EsrtProtocol = NULL;\r
- *AreAllImagesProcessed = FALSE;\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
- DumpFmpCapsule(CapsuleHeader);\r
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\r
+ continue;\r
+ }\r
\r
- FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\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 (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
- return EFI_INVALID_PARAMETER;\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
- ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
\r
- ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
+ FreePool (HandleBuffer);\r
\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
+ 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[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
+EFI_STATUS\r
+GetFmpHandleBufferByType (\r
+ IN EFI_GUID *UpdateImageTypeId,\r
+ IN UINT64 UpdateHardwareInstance,\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 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
+ 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
- //\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
+ 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
- //\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
+ MatchedNumberOfHandles = 0;\r
\r
- DriverDevicePath = AppendDevicePathNode (NULL, &MemMapNode.Header);\r
- if (DriverDevicePath == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\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
- for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\r
- if (FmpCapsuleHeader->PayloadItemCount == 0 && 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 = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];\r
- } else {\r
- DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];\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
- 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
+ for (Index = 0; Index < NumberOfHandles; Index++) {\r
+ Status = gBS->HandleProtocol(\r
+ HandleBuffer[Index],\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
);\r
- DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));\r
if (EFI_ERROR(Status)) {\r
- StatusRet = Status;\r
- goto EXIT;\r
+ continue;\r
}\r
\r
- DEBUG((DEBUG_INFO, "FmpCapsule: StartImage ...\n"));\r
- Status = gBS->StartImage(\r
- ImageHandle,\r
- &ExitDataSize,\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
- DEBUG((DEBUG_INFO, "FmpCapsule: StartImage - %r\n", Status));\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
- DEBUG ((DEBUG_ERROR, "Driver Return Status = %r\n", Status));\r
- StatusRet = Status;\r
- goto EXIT;\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
+ 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
+ }\r
+ TempFmpImageInfo = (EFI_FIRMWARE_IMAGE_DESCRIPTOR *)((UINT8 *)TempFmpImageInfo + DescriptorSize);\r
+ }\r
+ FreePool(FmpImageInfoBuf);\r
}\r
\r
- //\r
- // 2. Route payload to right FMP instance\r
- //\r
- DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));\r
+ FreePool (HandleBuffer);\r
\r
- Status = gBS->LocateHandleBuffer (\r
- ByProtocol,\r
+ if (MatchedNumberOfHandles == 0) {\r
+ return EFI_NOT_FOUND;\r
+ }\r
+\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
+\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
- &NumberOfHandles,\r
- &HandleBuffer\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ return 0;\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
+ FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
+ if (FmpImageInfoBuf == NULL) {\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
- continue;\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
- FmpImageInfoBuf = NULL;\r
- FmpImageInfoBuf = AllocateZeroPool (ImageInfoSize);\r
- if (FmpImageInfoBuf == NULL) {\r
- StatusRet = EFI_OUT_OF_RESOURCES;\r
- goto EXIT;\r
- }\r
+/**\r
+ Set FMP image data.\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
+ @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
- //\r
- // If FMP GetInformation interface failed, skip this resource\r
- //\r
- if (EFI_ERROR(Status)) {\r
- FreePool(FmpImageInfoBuf);\r
- continue;\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
+ EFI_FIRMWARE_MANAGEMENT_UPDATE_IMAGE_PROGRESS ProgressCallback;\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
+ Status = gBS->HandleProtocol(\r
+ Handle,\r
+ &gEfiFirmwareManagementProtocolGuid,\r
+ (VOID **)&Fmp\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
\r
- if (PackageVersionName != NULL) {\r
- FreePool(PackageVersionName);\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
- 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
+ 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 (CompareGuid(&ImageHeader->UpdateImageTypeId, &TempFmpImageInfo->ImageTypeId) &&\r
- ImageHeader->UpdateImageIndex == TempFmpImageInfo->ImageIndex) {\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
- );\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
+ 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
+\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
+ 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
+ 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 SyncEsrtFmp 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
- FreePool(FmpImageInfoBuf);\r
+ EsrtEntry.LastAttemptVersion = 0;\r
+ EsrtProtocol->UpdateEsrtEntry(&EsrtEntry);\r
}\r
}\r
+}\r
+\r
+/**\r
+ Process Firmware management protocol data capsule.\r
+\r
+ This function assumes the caller validated the capsule by using\r
+ ValidateFmpCapsule(), so that all fields in EFI_CAPSULE_HEADER,\r
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER and\r
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER are correct.\r
+\r
+ This function need support nested FMP capsule.\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
+ @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 *ResetRequired OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *FmpCapsuleHeader;\r
+ EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader;\r
+ UINT64 *ItemOffsetList;\r
+ UINT32 ItemNum;\r
+ UINTN Index;\r
+ EFI_HANDLE *HandleBuffer;\r
+ BOOLEAN *ResetRequiredBuffer;\r
+ UINTN NumberOfHandles;\r
+ UINTN DriverLen;\r
+ UINT64 UpdateHardwareInstance;\r
+ UINTN Index2;\r
+ BOOLEAN NotReady;\r
+ BOOLEAN Abort;\r
+\r
+ if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
+ return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);\r
+ }\r
+\r
+ NotReady = FALSE;\r
+ Abort = FALSE;\r
+\r
+ DumpFmpCapsule(CapsuleHeader);\r
+\r
+ FmpCapsuleHeader = (EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER *) ((UINT8 *) CapsuleHeader + CapsuleHeader->HeaderSize);\r
+\r
+ if (FmpCapsuleHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_HEADER_INIT_VERSION) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ ItemOffsetList = (UINT64 *)(FmpCapsuleHeader + 1);\r
+\r
+ ItemNum = FmpCapsuleHeader->EmbeddedDriverCount + FmpCapsuleHeader->PayloadItemCount;\r
\r
//\r
- // final check for AreAllImagesProcessed\r
+ // capsule in which driver count and payload count are both zero is not processed.\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
+ if (ItemNum == 0) {\r
+ return EFI_SUCCESS;\r
+ }\r
\r
- if (!IsFmpCapsuleProcessed(CapsuleHeader, Index - FmpCapsuleHeader->EmbeddedDriverCount, ImageHeader)) {\r
- *AreAllImagesProcessed = FALSE;\r
- break;\r
+ //\r
+ // 1. Try to load & start all the drivers within capsule\r
+ //\r
+ for (Index = 0; Index < FmpCapsuleHeader->EmbeddedDriverCount; Index++) {\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 = CapsuleHeader->CapsuleImageSize - CapsuleHeader->HeaderSize - (UINTN)ItemOffsetList[Index];\r
+ } else {\r
+ DriverLen = (UINTN)ItemOffsetList[Index + 1] - (UINTN)ItemOffsetList[Index];\r
+ }\r
+\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
+ return Status;\r
}\r
}\r
\r
-EXIT:\r
+ //\r
+ // 2. Route payload to right FMP instance\r
+ //\r
+ DEBUG((DEBUG_INFO, "FmpCapsule: route payload to right FMP instance ...\n"));\r
+\r
+ DumpAllFmpInfo ();\r
\r
- if (HandleBuffer != NULL) {\r
- FreePool(HandleBuffer);\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
+ UpdateHardwareInstance = 0;\r
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;\r
+ }\r
+\r
+ Status = GetFmpHandleBufferByType (\r
+ &ImageHeader->UpdateImageTypeId,\r
+ UpdateHardwareInstance,\r
+ &NumberOfHandles,\r
+ &HandleBuffer,\r
+ &ResetRequiredBuffer\r
+ );\r
+ if (EFI_ERROR(Status) ||\r
+ (HandleBuffer == NULL) ||\r
+ (ResetRequiredBuffer == NULL)) {\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
+ 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
+ Status = SetFmpImageData (\r
+ HandleBuffer[Index2],\r
+ ImageHeader,\r
+ Index - FmpCapsuleHeader->EmbeddedDriverCount\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
+ HandleBuffer[Index2],\r
+ CapsuleHeader,\r
+ Status,\r
+ Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
+ ImageHeader\r
+ );\r
+ }\r
+ if (HandleBuffer != NULL) {\r
+ FreePool(HandleBuffer);\r
+ }\r
+ if (ResetRequiredBuffer != NULL) {\r
+ FreePool(ResetRequiredBuffer);\r
+ }\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
- EFI_SYSTEM_RESOURCE_TABLE *Esrt;\r
EFI_SYSTEM_RESOURCE_ENTRY *EsrtEntry;\r
UINTN Index;\r
BOOLEAN EsrtGuidFound;\r
EFI_SYSTEM_RESOURCE_ENTRY Entry;\r
\r
EsrtGuidFound = FALSE;\r
-\r
- //\r
- // Check ESRT protocol\r
- //\r
- Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
- if (!EFI_ERROR(Status)) {\r
- Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);\r
- if (!EFI_ERROR(Status)) {\r
- EsrtGuidFound = TRUE;\r
- }\r
- }\r
-\r
- //\r
- // Check ESRT configuration table\r
- //\r
- if (!EsrtGuidFound) {\r
- Status = EfiGetSystemConfigurationTable(&gEfiSystemResourceTableGuid, (VOID **)&Esrt);\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 (mIsVirtualAddrConverted) {\r
+ if(mEsrtTable != NULL) {\r
+ EsrtEntry = (EFI_SYSTEM_RESOURCE_ENTRY *)(mEsrtTable + 1);\r
+ for (Index = 0; Index < mEsrtTable->FwResourceCount ; Index++, EsrtEntry++) {\r
if (CompareGuid(&EsrtEntry->FwClass, &CapsuleHeader->CapsuleGuid)) {\r
EsrtGuidFound = TRUE;\r
break;\r
}\r
}\r
}\r
+ } else {\r
+ //\r
+ // Check ESRT protocol\r
+ //\r
+ Status = gBS->LocateProtocol(&gEsrtManagementProtocolGuid, NULL, (VOID **)&EsrtProtocol);\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = EsrtProtocol->GetEsrtEntry(&CapsuleHeader->CapsuleGuid, &Entry);\r
+ if (!EFI_ERROR(Status)) {\r
+ EsrtGuidFound = TRUE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check Firmware Management Protocols\r
+ //\r
+ if (!EsrtGuidFound) {\r
+ Status = GetFmpHandleBufferByType (\r
+ &CapsuleHeader->CapsuleGuid,\r
+ 0,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ if (!EFI_ERROR(Status)) {\r
+ EsrtGuidFound = TRUE;\r
+ }\r
+ }\r
}\r
if (!EsrtGuidFound) {\r
return FALSE;\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
- 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
//\r
- // Press EFI FMP Capsule\r
+ // Process EFI FMP Capsule\r
//\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));\r
- Status = ProcessFmpCapsuleImage(CapsuleHeader, &AreAllImagesProcessed);\r
+ Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));\r
\r
- if (!AreAllImagesProcessed) {\r
- mAreAllImagesProcessed = FALSE;\r
- }\r
-\r
return Status;\r
}\r
\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
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_EVENT EndOfDxeEvent;\r
EFI_STATUS Status;\r
\r
Status = gBS->CreateEventEx (\r
DxeCapsuleLibEndOfDxe,\r
NULL,\r
&gEfiEndOfDxeEventGroupGuid,\r
- &EndOfDxeEvent\r
+ &mDxeCapsuleLibEndOfDxeEvent\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
\r
return EFI_SUCCESS;\r
}\r
+\r
+/**\r
+ The destructor function closes the End of DXE event.\r
+\r
+ @param ImageHandle The firmware allocated handle for the EFI image.\r
+ @param SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The destructor completed successfully.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+DxeCapsuleLibDestructor (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Close the End of DXE event.\r
+ //\r
+ Status = gBS->CloseEvent (mDxeCapsuleLibEndOfDxeEvent);\r
+ ASSERT_EFI_ERROR (Status);\r
+\r
+ return EFI_SUCCESS;\r
+}\r