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. + @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 was returned in Buffer, and the number of - handles in Buffer was returned in NoHandles. + @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; } }