X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=MdeModulePkg%2FLibrary%2FDxeCapsuleLibFmp%2FDxeCapsuleLib.c;h=f56809bb7019de467a887d9bb6899129a983e573;hb=c2cf8720a5aad74230767a1f11bade2d86de3745;hp=a1347b5ce67c8d409afbfbe8a31792f7a913a691;hpb=a891bd733781f5430abe0a670e1bbe79e16baa28;p=mirror_edk2.git diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c index a1347b5ce6..f56809bb70 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -268,10 +267,6 @@ ValidateFmpCapsule ( } FmpImageSize = (UINTN)EndOfPayload - ItemOffsetList[Index]; - if (FmpImageSize < OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance)) { - DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER\n", FmpImageSize)); - return EFI_INVALID_PARAMETER; - } FmpImageHeaderSize = sizeof(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER); if ((ImageHeader->Version > EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) || (ImageHeader->Version < 1)) { @@ -281,6 +276,10 @@ ValidateFmpCapsule ( if (ImageHeader->Version < EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER_INIT_VERSION) { FmpImageHeaderSize = OFFSET_OF(EFI_FIRMWARE_MANAGEMENT_CAPSULE_IMAGE_HEADER, UpdateHardwareInstance); } + if (FmpImageSize < FmpImageHeaderSize) { + DEBUG((DEBUG_ERROR, "FmpImageSize(0x%lx) < FmpImageHeaderSize(0x%x)\n", FmpImageSize, FmpImageHeaderSize)); + return EFI_INVALID_PARAMETER; + } // No overflow if (FmpImageSize != (UINT64)FmpImageHeaderSize + (UINT64)ImageHeader->UpdateImageSize + (UINT64)ImageHeader->UpdateVendorCodeSize) { @@ -610,6 +609,8 @@ DumpAllFmpInfo ( FreePool(FmpImageInfoBuf); } + FreePool (HandleBuffer); + return ; } @@ -618,11 +619,14 @@ DumpAllFmpInfo ( @param[in] UpdateImageTypeId Used to identify device firmware targeted by this update. @param[in] UpdateHardwareInstance The HardwareInstance to target with this update. - @param[in,out] NoHandles The number of handles returned in Buffer. - @param[out] Buffer[out] A pointer to the buffer to return the requested array of handles. - - @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of - handles in Buffer was returned in NoHandles. + @param[out] NoHandles The number of handles returned in HandleBuf. + @param[out] HandleBuf A pointer to the buffer to return the requested array of handles. + @param[out] ResetRequiredBuf A pointer to the buffer to return reset required flag for + the requested array of handles. + + @retval EFI_SUCCESS The array of handles and their reset required flag were returned in + HandleBuf and ResetRequiredBuf, and the number of handles in HandleBuf + was returned in NoHandles. @retval EFI_NOT_FOUND No handles match the search. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results. **/ @@ -630,14 +634,16 @@ EFI_STATUS GetFmpHandleBufferByType ( IN EFI_GUID *UpdateImageTypeId, IN UINT64 UpdateHardwareInstance, - IN OUT UINTN *NoHandles, - OUT EFI_HANDLE **Buffer + OUT UINTN *NoHandles, OPTIONAL + OUT EFI_HANDLE **HandleBuf, OPTIONAL + OUT BOOLEAN **ResetRequiredBuf OPTIONAL ) { EFI_STATUS Status; EFI_HANDLE *HandleBuffer; UINTN NumberOfHandles; EFI_HANDLE *MatchedHandleBuffer; + BOOLEAN *MatchedResetRequiredBuffer; UINTN MatchedNumberOfHandles; EFI_FIRMWARE_MANAGEMENT_PROTOCOL *Fmp; UINTN Index; @@ -651,8 +657,15 @@ GetFmpHandleBufferByType ( UINTN Index2; EFI_FIRMWARE_IMAGE_DESCRIPTOR *TempFmpImageInfo; - *NoHandles = 0; - *Buffer = NULL; + if (NoHandles != NULL) { + *NoHandles = 0; + } + if (HandleBuf != NULL) { + *HandleBuf = NULL; + } + if (ResetRequiredBuf != NULL) { + *ResetRequiredBuf = NULL; + } Status = gBS->LocateHandleBuffer ( ByProtocol, @@ -666,10 +679,26 @@ GetFmpHandleBufferByType ( } MatchedNumberOfHandles = 0; - MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles); - if (MatchedHandleBuffer == NULL) { - FreePool (HandleBuffer); - return EFI_OUT_OF_RESOURCES; + + MatchedHandleBuffer = NULL; + if (HandleBuf != NULL) { + MatchedHandleBuffer = AllocateZeroPool (sizeof(EFI_HANDLE) * NumberOfHandles); + if (MatchedHandleBuffer == NULL) { + FreePool (HandleBuffer); + return EFI_OUT_OF_RESOURCES; + } + } + + MatchedResetRequiredBuffer = NULL; + if (ResetRequiredBuf != NULL) { + MatchedResetRequiredBuffer = AllocateZeroPool (sizeof(BOOLEAN) * NumberOfHandles); + if (MatchedResetRequiredBuffer == NULL) { + if (MatchedHandleBuffer != NULL) { + FreePool (MatchedHandleBuffer); + } + FreePool (HandleBuffer); + return EFI_OUT_OF_RESOURCES; + } } for (Index = 0; Index < NumberOfHandles; Index++) { @@ -731,7 +760,15 @@ GetFmpHandleBufferByType ( if ((UpdateHardwareInstance == 0) || ((FmpImageInfoDescriptorVer >= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) && (UpdateHardwareInstance == TempFmpImageInfo->HardwareInstance))) { - MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index]; + if (MatchedHandleBuffer != NULL) { + MatchedHandleBuffer[MatchedNumberOfHandles] = HandleBuffer[Index]; + } + if (MatchedResetRequiredBuffer != NULL) { + MatchedResetRequiredBuffer[MatchedNumberOfHandles] = (((TempFmpImageInfo->AttributesSupported & + IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0) && + ((TempFmpImageInfo->AttributesSetting & + IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0)); + } MatchedNumberOfHandles++; break; } @@ -741,12 +778,21 @@ GetFmpHandleBufferByType ( FreePool(FmpImageInfoBuf); } + FreePool (HandleBuffer); + if (MatchedNumberOfHandles == 0) { return EFI_NOT_FOUND; } - *NoHandles = MatchedNumberOfHandles; - *Buffer = MatchedHandleBuffer; + if (NoHandles != NULL) { + *NoHandles = MatchedNumberOfHandles; + } + if (HandleBuf != NULL) { + *HandleBuf = MatchedHandleBuffer; + } + if (ResetRequiredBuf != NULL) { + *ResetRequiredBuf = MatchedResetRequiredBuffer; + } return EFI_SUCCESS; } @@ -1047,7 +1093,7 @@ RecordFmpCapsuleStatus ( // // Update EsrtEntry For V1, V2 FMP instance. - // V3 FMP ESRT cache will be synced up through EsrtSyncFmp interface + // V3 FMP ESRT cache will be synced up through SyncEsrtFmp interface // FmpImageInfoDescriptorVer = GetFmpImageInfoDescriptorVer (Handle); if (FmpImageInfoDescriptorVer < EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) { @@ -1074,7 +1120,8 @@ RecordFmpCapsuleStatus ( This function need support nested FMP capsule. - @param[in] CapsuleHeader Points to a capsule header. + @param[in] CapsuleHeader Points to a capsule header. + @param[out] ResetRequired Indicates whether reset is required or not. @retval EFI_SUCESS Process Capsule Image successfully. @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. @@ -1084,7 +1131,8 @@ RecordFmpCapsuleStatus ( **/ EFI_STATUS ProcessFmpCapsuleImage ( - IN EFI_CAPSULE_HEADER *CapsuleHeader + IN EFI_CAPSULE_HEADER *CapsuleHeader, + OUT BOOLEAN *ResetRequired OPTIONAL ) { EFI_STATUS Status; @@ -1094,6 +1142,7 @@ ProcessFmpCapsuleImage ( UINT32 ItemNum; UINTN Index; EFI_HANDLE *HandleBuffer; + BOOLEAN *ResetRequiredBuffer; UINTN NumberOfHandles; UINTN DriverLen; UINT64 UpdateHardwareInstance; @@ -1102,7 +1151,7 @@ ProcessFmpCapsuleImage ( BOOLEAN Abort; if (!IsFmpCapsuleGuid(&CapsuleHeader->CapsuleGuid)) { - return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize)); + return ProcessFmpCapsuleImage ((EFI_CAPSULE_HEADER *)((UINTN)CapsuleHeader + CapsuleHeader->HeaderSize), ResetRequired); } NotReady = FALSE; @@ -1172,9 +1221,12 @@ ProcessFmpCapsuleImage ( &ImageHeader->UpdateImageTypeId, UpdateHardwareInstance, &NumberOfHandles, - &HandleBuffer + &HandleBuffer, + &ResetRequiredBuffer ); - if (EFI_ERROR(Status)) { + if (EFI_ERROR(Status) || + (HandleBuffer == NULL) || + (ResetRequiredBuffer == NULL)) { NotReady = TRUE; RecordFmpCapsuleStatus ( NULL, @@ -1205,6 +1257,10 @@ ProcessFmpCapsuleImage ( ); if (Status != EFI_SUCCESS) { Abort = TRUE; + } else { + if (ResetRequired != NULL) { + *ResetRequired |= ResetRequiredBuffer[Index2]; + } } RecordFmpCapsuleStatus ( @@ -1218,6 +1274,9 @@ ProcessFmpCapsuleImage ( if (HandleBuffer != NULL) { FreePool(HandleBuffer); } + if (ResetRequiredBuffer != NULL) { + FreePool(ResetRequiredBuffer); + } } if (NotReady) { @@ -1252,8 +1311,6 @@ IsNestedFmpCapsule ( UINTN NestedCapsuleSize; ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol; EFI_SYSTEM_RESOURCE_ENTRY Entry; - EFI_HANDLE *HandleBuffer; - UINTN NumberOfHandles; EsrtGuidFound = FALSE; if (mIsVirtualAddrConverted) { @@ -1282,19 +1339,16 @@ IsNestedFmpCapsule ( // Check Firmware Management Protocols // if (!EsrtGuidFound) { - HandleBuffer = NULL; Status = GetFmpHandleBufferByType ( &CapsuleHeader->CapsuleGuid, 0, - &NumberOfHandles, - &HandleBuffer + NULL, + NULL, + NULL ); if (!EFI_ERROR(Status)) { EsrtGuidFound = TRUE; } - if (HandleBuffer != NULL) { - FreePool (HandleBuffer); - } } } if (!EsrtGuidFound) { @@ -1367,6 +1421,12 @@ SupportCapsuleImage ( } if (IsFmpCapsule(CapsuleHeader)) { + // + // Fake capsule header is valid case in QueryCapsuleCpapbilities(). + // + if (CapsuleHeader->HeaderSize == CapsuleHeader->CapsuleImageSize) { + return EFI_SUCCESS; + } // // Check layout of FMP capsule // @@ -1382,6 +1442,7 @@ SupportCapsuleImage ( Caution: This function may receive untrusted input. @param[in] CapsuleHeader Points to a capsule header. + @param[out] ResetRequired Indicates whether reset is required or not. @retval EFI_SUCESS Process Capsule Image successfully. @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. @@ -1390,8 +1451,9 @@ SupportCapsuleImage ( **/ EFI_STATUS EFIAPI -ProcessCapsuleImage ( - IN EFI_CAPSULE_HEADER *CapsuleHeader +ProcessThisCapsuleImage ( + IN EFI_CAPSULE_HEADER *CapsuleHeader, + OUT BOOLEAN *ResetRequired OPTIONAL ) { EFI_STATUS Status; @@ -1428,7 +1490,7 @@ ProcessCapsuleImage ( // Process EFI FMP Capsule // DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage ...\n")); - Status = ProcessFmpCapsuleImage(CapsuleHeader); + Status = ProcessFmpCapsuleImage(CapsuleHeader, ResetRequired); DEBUG((DEBUG_INFO, "ProcessFmpCapsuleImage - %r\n", Status)); return Status; @@ -1437,6 +1499,27 @@ ProcessCapsuleImage ( return EFI_UNSUPPORTED; } +/** + The firmware implements to process the capsule image. + + Caution: This function may receive untrusted input. + + @param[in] CapsuleHeader Points to a capsule header. + + @retval EFI_SUCESS Process Capsule Image successfully. + @retval EFI_UNSUPPORTED Capsule image is not supported by the firmware. + @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. + @retval EFI_OUT_OF_RESOURCES Not enough memory. +**/ +EFI_STATUS +EFIAPI +ProcessCapsuleImage ( + IN EFI_CAPSULE_HEADER *CapsuleHeader + ) +{ + return ProcessThisCapsuleImage (CapsuleHeader, NULL); +} + /** Callback function executed when the EndOfDxe event group is signaled.