From 69feaa37aeca6386de0fc635a1287e6e31851d7a Mon Sep 17 00:00:00 2001 From: Star Zeng Date: Thu, 26 Jul 2018 13:38:34 +0800 Subject: [PATCH] MdeModulePkg DxeCapsuleLib: Use Attr to know whether reset is required Current DxeCapsuleLibFmp always do reset for FMP capsule. Actually, the code should use Attributes from FMP descriptor to know whether reset is required or not. Cc: Jiewen Yao Cc: Michael D Kinney Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Star Zeng Reviewed-by: Jiewen Yao --- .../Library/DxeCapsuleLibFmp/DxeCapsuleLib.c | 134 ++++++++++++++---- .../DxeCapsuleLibFmp/DxeCapsuleProcessLib.c | 40 ++++-- 2 files changed, 134 insertions(+), 40 deletions(-) diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c index 3c283e2513..d4026dd5c7 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleLib.c @@ -618,11 +618,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 +633,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 +656,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 +678,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 +759,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; } @@ -745,8 +781,15 @@ GetFmpHandleBufferByType ( 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; } @@ -1074,7 +1117,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 +1128,8 @@ RecordFmpCapsuleStatus ( **/ EFI_STATUS ProcessFmpCapsuleImage ( - IN EFI_CAPSULE_HEADER *CapsuleHeader + IN EFI_CAPSULE_HEADER *CapsuleHeader, + OUT BOOLEAN *ResetRequired OPTIONAL ) { EFI_STATUS Status; @@ -1094,6 +1139,7 @@ ProcessFmpCapsuleImage ( UINT32 ItemNum; UINTN Index; EFI_HANDLE *HandleBuffer; + BOOLEAN *ResetRequiredBuffer; UINTN NumberOfHandles; UINTN DriverLen; UINT64 UpdateHardwareInstance; @@ -1102,7 +1148,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,7 +1218,8 @@ ProcessFmpCapsuleImage ( &ImageHeader->UpdateImageTypeId, UpdateHardwareInstance, &NumberOfHandles, - &HandleBuffer + &HandleBuffer, + &ResetRequiredBuffer ); if (EFI_ERROR(Status)) { NotReady = TRUE; @@ -1205,6 +1252,10 @@ ProcessFmpCapsuleImage ( ); if (Status != EFI_SUCCESS) { Abort = TRUE; + } else { + if (ResetRequired != NULL) { + *ResetRequired |= ResetRequiredBuffer[Index2]; + } } RecordFmpCapsuleStatus ( @@ -1218,6 +1269,9 @@ ProcessFmpCapsuleImage ( if (HandleBuffer != NULL) { FreePool(HandleBuffer); } + if (ResetRequiredBuffer != NULL) { + FreePool(ResetRequiredBuffer); + } } if (NotReady) { @@ -1252,8 +1306,6 @@ IsNestedFmpCapsule ( UINTN NestedCapsuleSize; ESRT_MANAGEMENT_PROTOCOL *EsrtProtocol; EFI_SYSTEM_RESOURCE_ENTRY Entry; - EFI_HANDLE *HandleBuffer; - UINTN NumberOfHandles; EsrtGuidFound = FALSE; if (mIsVirtualAddrConverted) { @@ -1282,19 +1334,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) { @@ -1382,6 +1431,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 +1440,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 +1479,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 +1488,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. diff --git a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c index 26ca4e295f..176dea1960 100644 --- a/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c +++ b/MdeModulePkg/Library/DxeCapsuleLibFmp/DxeCapsuleProcessLib.c @@ -99,12 +99,32 @@ IsValidCapsuleHeader ( ); extern BOOLEAN mDxeCapsuleLibEndOfDxe; -BOOLEAN mNeedReset; +BOOLEAN mNeedReset = FALSE; VOID **mCapsulePtr; EFI_STATUS *mCapsuleStatusArray; UINT32 mCapsuleTotalNumber; +/** + The firmware implements to process the capsule image. + + 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. + @retval EFI_VOLUME_CORRUPTED FV volume in the capsule is corrupted. + @retval EFI_OUT_OF_RESOURCES Not enough memory. +**/ +EFI_STATUS +EFIAPI +ProcessThisCapsuleImage ( + IN EFI_CAPSULE_HEADER *CapsuleHeader, + OUT BOOLEAN *ResetRequired OPTIONAL + ); + /** Function indicate the current completion progress of the firmware update. Platform may override with own specific progress function. @@ -381,6 +401,7 @@ ProcessTheseCapsules ( UINT32 Index; ESRT_MANAGEMENT_PROTOCOL *EsrtManagement; UINT16 EmbeddedDriverCount; + BOOLEAN ResetRequired; REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeProcessCapsulesBegin))); @@ -416,11 +437,11 @@ ProcessTheseCapsules ( for (Index = 0; Index < mCapsuleTotalNumber; Index++) { CapsuleHeader = (EFI_CAPSULE_HEADER*) mCapsulePtr [Index]; if (CompareGuid (&CapsuleHeader->CapsuleGuid, &gWindowsUxCapsuleGuid)) { - DEBUG ((DEBUG_INFO, "ProcessCapsuleImage (Ux) - 0x%x\n", CapsuleHeader)); + DEBUG ((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - 0x%x\n", CapsuleHeader)); DEBUG ((DEBUG_INFO, "Display logo capsule is found.\n")); - Status = ProcessCapsuleImage (CapsuleHeader); + Status = ProcessThisCapsuleImage (CapsuleHeader, NULL); mCapsuleStatusArray [Index] = EFI_SUCCESS; - DEBUG((DEBUG_INFO, "ProcessCapsuleImage (Ux) - %r\n", Status)); + DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage (Ux) - %r\n", Status)); break; } } @@ -454,10 +475,11 @@ ProcessTheseCapsules ( } if ((!FirstRound) || (EmbeddedDriverCount == 0)) { - DEBUG((DEBUG_INFO, "ProcessCapsuleImage - 0x%x\n", CapsuleHeader)); - Status = ProcessCapsuleImage (CapsuleHeader); + DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - 0x%x\n", CapsuleHeader)); + ResetRequired = FALSE; + Status = ProcessThisCapsuleImage (CapsuleHeader, &ResetRequired); mCapsuleStatusArray [Index] = Status; - DEBUG((DEBUG_INFO, "ProcessCapsuleImage - %r\n", Status)); + DEBUG((DEBUG_INFO, "ProcessThisCapsuleImage - %r\n", Status)); if (Status != EFI_NOT_READY) { if (EFI_ERROR(Status)) { @@ -467,8 +489,8 @@ ProcessTheseCapsules ( REPORT_STATUS_CODE(EFI_PROGRESS_CODE, (EFI_SOFTWARE | PcdGet32(PcdStatusCodeSubClassCapsule) | PcdGet32(PcdCapsuleStatusCodeUpdateFirmwareSuccess))); } - if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0 || - IsFmpCapsule(CapsuleHeader)) { + mNeedReset |= ResetRequired; + if ((CapsuleHeader->Flags & PcdGet16(PcdSystemRebootAfterCapsuleProcessFlag)) != 0) { mNeedReset = TRUE; } } -- 2.39.2