ValidateFmpCapsule(), and DisplayCapsuleImage() receives untrusted input and\r
performs basic validation.\r
\r
- Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- 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 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\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
@param[in] PayloadIndex FMP payload index\r
@param[in] ImageHeader FMP image header\r
@param[in] FmpDevicePath DevicePath associated with the FMP producer\r
+ @param[in] CapFileName Capsule file name\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_STATUS CapsuleStatus,\r
IN UINTN PayloadIndex,\r
IN EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER *ImageHeader,\r
- IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath OPTIONAL\r
+ IN EFI_DEVICE_PATH_PROTOCOL *FmpDevicePath, OPTIONAL\r
+ IN CHAR16 *CapFileName OPTIONAL\r
);\r
\r
/**\r
IN UINTN Completion\r
);\r
\r
+/**\r
+ Return if this capsule is a capsule name capsule, based upon CapsuleHeader.\r
+\r
+ @param[in] CapsuleHeader A pointer to EFI_CAPSULE_HEADER\r
+\r
+ @retval TRUE It is a capsule name capsule.\r
+ @retval FALSE It is not a capsule name capsule.\r
+**/\r
+BOOLEAN\r
+IsCapsuleNameCapsule (\r
+ IN EFI_CAPSULE_HEADER *CapsuleHeader\r
+ )\r
+{\r
+ return CompareGuid (&CapsuleHeader->CapsuleGuid, &gEdkiiCapsuleOnDiskNameGuid);\r
+}\r
+\r
/**\r
Return if this CapsuleGuid is a FMP capsule GUID or not.\r
\r
DEBUG((DEBUG_ERROR, "ImageHeader->Version(0x%x) Unknown\n", ImageHeader->Version));\r
return EFI_INVALID_PARAMETER;\r
}\r
- if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ if (ImageHeader->Version == 1) {\r
FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
+ } else if (ImageHeader->Version == 2) {\r
+ FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, ImageCapsuleSupport);\r
}\r
if (FmpImageSize < FmpImageHeaderSize) {\r
DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize, FmpImageHeaderSize));\r
DEBUG((DEBUG_VERBOSE, " UpdateImageIndex - 0x%x\n", ImageHeader->UpdateImageIndex));\r
DEBUG((DEBUG_VERBOSE, " UpdateImageSize - 0x%x\n", ImageHeader->UpdateImageSize));\r
DEBUG((DEBUG_VERBOSE, " UpdateVendorCodeSize - 0x%x\n", ImageHeader->UpdateVendorCodeSize));\r
- if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ if (ImageHeader->Version >= 2) {\r
DEBUG((DEBUG_VERBOSE, " UpdateHardwareInstance - 0x%lx\n", ImageHeader->UpdateHardwareInstance));\r
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ DEBUG((DEBUG_VERBOSE, " ImageCapsuleSupport - 0x%lx\n", ImageHeader->ImageCapsuleSupport));\r
+ }\r
}\r
}\r
}\r
MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index];\r
}\r
if (MatchedResetRequiredBuffer != NULL) {\r
- MatchedResetRequiredBuffer[MatchedNumberOfHandles] = (((TempFmpImageInfo->AttributesSupported & \r
+ MatchedResetRequiredBuffer[MatchedNumberOfHandles] = (((TempFmpImageInfo->AttributesSupported &\r
IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) &&\r
((TempFmpImageInfo->AttributesSetting &\r
IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0));\r
} else {\r
//\r
// If the EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER is version 1,\r
- // Header should exclude UpdateHardwareInstance field\r
+ // Header should exclude UpdateHardwareInstance field, and\r
+ // ImageCapsuleSupport field if version is 2.\r
//\r
- Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
+ if (ImageHeader->Version == 1) {\r
+ Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance);\r
+ } else {\r
+ Image = (UINT8 *)ImageHeader + OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, ImageCapsuleSupport);\r
+ }\r
}\r
\r
if (ImageHeader->UpdateVendorCodeSize == 0) {\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
+ if (ImageHeader->Version >= 2) {\r
DEBUG((DEBUG_INFO, "(UpdateHardwareInstance - 0x%x)", ImageHeader->UpdateHardwareInstance));\r
+ if (ImageHeader->Version >= EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) {\r
+ DEBUG((DEBUG_INFO, "(ImageCapsuleSupport - 0x%x)", ImageHeader->ImageCapsuleSupport));\r
+ }\r
}\r
DEBUG((DEBUG_INFO, "\n"));\r
\r
);\r
DEBUG((DEBUG_INFO, "FmpCapsule: LoadImage - %r\n", Status));\r
if (EFI_ERROR(Status)) {\r
+ //\r
+ // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created\r
+ // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.\r
+ // If the caller doesn't have the option to defer the execution of an image, we should\r
+ // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.\r
+ //\r
+ if (Status == EFI_SECURITY_VIOLATION) {\r
+ gBS->UnloadImage (ImageHandle);\r
+ }\r
FreePool(DriverDevicePath);\r
return Status;\r
}\r
/**\r
Record FMP capsule status.\r
\r
- @param[in] Handle A FMP handle.\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
+ @param[in] CapFileName Capsule file name\r
**/\r
VOID\r
RecordFmpCapsuleStatus (\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 CHAR16 *CapFileName OPTIONAL\r
)\r
{\r
EFI_STATUS Status;\r
CapsuleStatus,\r
PayloadIndex,\r
ImageHeader,\r
- FmpDevicePath\r
+ FmpDevicePath,\r
+ CapFileName\r
);\r
\r
//\r
This function need support nested FMP capsule.\r
\r
@param[in] CapsuleHeader Points to a capsule header.\r
+ @param[in] CapFileName Capsule file name.\r
@param[out] ResetRequired Indicates whether reset is required or not.\r
\r
@retval EFI_SUCESS Process Capsule Image successfully.\r
EFI_STATUS\r
ProcessFmpCapsuleImage (\r
IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
+ IN CHAR16 *CapFileName, OPTIONAL\r
OUT BOOLEAN *ResetRequired OPTIONAL\r
)\r
{\r
BOOLEAN Abort;\r
\r
if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) {\r
- return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired);\r
+ return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), CapFileName, ResetRequired);\r
}\r
\r
NotReady = FALSE;\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
+ ///\r
+ /// UpdateHardwareInstance field was added in Version 2\r
+ ///\r
+ if (ImageHeader->Version >= 2) {\r
UpdateHardwareInstance = ImageHeader->UpdateHardwareInstance;\r
}\r
\r
CapsuleHeader,\r
EFI_NOT_READY,\r
Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
- ImageHeader\r
+ ImageHeader,\r
+ CapFileName\r
);\r
continue;\r
}\r
CapsuleHeader,\r
EFI_ABORTED,\r
Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
- ImageHeader\r
+ ImageHeader,\r
+ CapFileName\r
);\r
continue;\r
}\r
CapsuleHeader,\r
Status,\r
Index - FmpCapsuleHeader->EmbeddedDriverCount,\r
- ImageHeader\r
+ ImageHeader,\r
+ CapFileName\r
);\r
}\r
if (HandleBuffer != NULL) {\r
return EFI_SUCCESS;\r
}\r
\r
+ //\r
+ // Check capsule file name capsule\r
+ //\r
+ if (IsCapsuleNameCapsule(CapsuleHeader)) {\r
+ return EFI_SUCCESS;\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[in] CapFileName Capsule file name.\r
@param[out] ResetRequired Indicates whether reset is required or not.\r
\r
@retval EFI_SUCESS Process Capsule Image successfully.\r
EFIAPI\r
ProcessThisCapsuleImage (\r
IN EFI_CAPSULE_HEADER *CapsuleHeader,\r
+ IN CHAR16 *CapFileName, OPTIONAL\r
OUT BOOLEAN *ResetRequired OPTIONAL\r
)\r
{\r
// Process EFI FMP Capsule\r
//\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n"));\r
- Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired);\r
+ Status = ProcessFmpCapsuleImage(CapsuleHeader, CapFileName, ResetRequired);\r
DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status));\r
\r
return Status;\r
IN EFI_CAPSULE_HEADER *CapsuleHeader\r
)\r
{\r
- return ProcessThisCapsuleImage (CapsuleHeader, NULL);\r
+ return ProcessThisCapsuleImage (CapsuleHeader, NULL, NULL);\r
}\r
\r
/**\r