diff --git a/DcpmPkg/cli/Common.c b/DcpmPkg/cli/Common.c index ba8b1a95..42da5ae9 100644 --- a/DcpmPkg/cli/Common.c +++ b/DcpmPkg/cli/Common.c @@ -1220,6 +1220,9 @@ MatchCliReturnCode( case NVM_ERR_REGION_GOAL_NAMESPACE_EXISTS: case NVM_ERR_REGION_REMAINING_SIZE_NOT_IN_LAST_PROPERTY: case NVM_ERR_ARS_IN_PROGRESS: + case NVM_ERR_FWUPDATE_IN_PROGRESS: + case NVM_ERR_OVERWRITE_DIMM_IN_PROGRESS: + case NVM_ERR_UNKNOWN_LONG_OP_IN_PROGRESS: case NVM_ERR_APPDIRECT_IN_SYSTEM: case NVM_ERR_OPERATION_NOT_SUPPORTED_BY_MIXED_SKU: case NVM_ERR_SECURE_ERASE_NAMESPACE_EXISTS: diff --git a/DcpmPkg/common/NvmSharedDefs.h b/DcpmPkg/common/NvmSharedDefs.h index ae3a3489..e21fe49f 100644 --- a/DcpmPkg/common/NvmSharedDefs.h +++ b/DcpmPkg/common/NvmSharedDefs.h @@ -179,6 +179,9 @@ typedef enum _NvmStatusCode { NVM_SUCCESS_NO_EVENT_FOUND = 302, ///< Error: No events found in the event log NVM_ERR_FILE_NOT_FOUND = 303, ///< Error: No events found in the event log + NVM_ERR_OVERWRITE_DIMM_IN_PROGRESS = 304, ///< Error: No events found in the event log + NVM_ERR_FWUPDATE_IN_PROGRESS = 305, ///< Error: No events found in the event log + NVM_ERR_UNKNOWN_LONG_OP_IN_PROGRESS = 306, ///< Error: No events found in the event log NVM_LAST_STATUS_VALUE } NvmStatusCode; diff --git a/DcpmPkg/common/NvmStatus.c b/DcpmPkg/common/NvmStatus.c index 61651d43..d4543b46 100644 --- a/DcpmPkg/common/NvmStatus.c +++ b/DcpmPkg/common/NvmStatus.c @@ -535,6 +535,12 @@ GetSingleNvmStatusCodeMessage( case NVM_ERR_ARS_IN_PROGRESS: return HiiGetString(HiiHandle, STRING_TOKEN(STR_DCPMM_STATUS_ERR_ARS_IN_PROGRESS), NULL); + case NVM_ERR_FWUPDATE_IN_PROGRESS: + return HiiGetString(HiiHandle, STRING_TOKEN(STR_DCPMM_STATUS_ERR_FWUPDATE_IN_PROGRESS), NULL); + case NVM_ERR_OVERWRITE_DIMM_IN_PROGRESS: + return HiiGetString(HiiHandle, STRING_TOKEN(STR_DCPMM_STATUS_ERR_OVERWRITE_DIMM_IN_PROGRESS), NULL); + case NVM_ERR_UNKNOWN_LONG_OP_IN_PROGRESS: + return HiiGetString(HiiHandle, STRING_TOKEN(STR_DCPMM_STATUS_ERR_UNKNOWN_LONG_OP_IN_PROGRESS), NULL); case NVM_ERR_APPDIRECT_IN_SYSTEM: return HiiGetString(HiiHandle, STRING_TOKEN(STR_DCPMM_STATUS_ERR_APPDIRECT_IN_SYSTEM), NULL); diff --git a/DcpmPkg/common/NvmStatus.uni b/DcpmPkg/common/NvmStatus.uni index e53a17d4..48db9da2 100644 Binary files a/DcpmPkg/common/NvmStatus.uni and b/DcpmPkg/common/NvmStatus.uni differ diff --git a/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.c b/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.c index 62d03891..6225acd5 100644 --- a/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.c +++ b/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.c @@ -5307,6 +5307,9 @@ UpdateFw( UINT32 VerificationFailures = 0; UINT32 ForceRequiredDimms = 0; + EFI_STATUS LongOpStatusReturnCode = 0; + NVM_STATUS LongOpNvmStatus = NVM_ERR_OPERATION_NOT_STARTED; + ZeroMem(pDimms, sizeof(pDimms)); NVDIMM_ENTRY(); @@ -5429,7 +5432,6 @@ UpdateFw( } else { pDimmsCanBeUpdated[Index] = TRUE; - DimmsToUpdate++; SetObjStatusForDimmWithErase(pCommandStatus, pDimms[Index], NVM_SUCCESS_IMAGE_EXAMINE_OK, TRUE); } #endif @@ -5451,7 +5453,6 @@ UpdateFw( } else { pDimmsCanBeUpdated[Index] = TRUE; - DimmsToUpdate++; SetObjStatusForDimmWithErase(pCommandStatus, pDimms[Index], NVM_SUCCESS_IMAGE_EXAMINE_OK, TRUE); } } @@ -5464,6 +5465,14 @@ UpdateFw( goto Finish; } + //count up the number of DIMMs to update + DimmsToUpdate = 0; + for (Index = 0; Index < DimmsNum; Index++) { + if (pDimmsCanBeUpdated[Index] == TRUE) { + DimmsToUpdate++; + } + } + if (DimmsToUpdate == 0) { if (pCommandStatus->GeneralStatus == NVM_ERR_OPERATION_NOT_STARTED) { NVDIMM_DBG("Found no DIMMs to update - either none were passed or none passed the verification checks"); @@ -5475,7 +5484,7 @@ UpdateFw( // upload FW image to all specified DIMMs for (Index = 0; Index < DimmsNum; Index++) { if (pDimmsCanBeUpdated[Index] == FALSE) { - NVDIMM_DBG("Skipping dimm %d. It is marked as not being capable of this update", pDimms[Index]->DeviceHandle.AsUint32); + NVDIMM_DBG("Skipping dimm %d. It is marked as not being currently capable of this update", pDimms[Index]->DeviceHandle.AsUint32); continue; } @@ -5492,14 +5501,23 @@ UpdateFw( if (ReturnCode != EFI_SUCCESS) { UpdateFailures++; - if (NvmStatus == NVM_SUCCESS) { - pCommandStatus->GeneralStatus = NVM_ERR_OPERATION_FAILED; - SetObjStatusForDimmWithErase(pCommandStatus, pDimms[Index], NVM_ERR_OPERATION_FAILED, TRUE); + + //Perform a check to see if it was a long operation that blocked the update and get more details about it + LongOpStatusReturnCode = CheckForLongOpStatusInProgress(pDimms[Index], &LongOpNvmStatus); + if (LongOpStatusReturnCode == EFI_SUCCESS && LongOpNvmStatus != NVM_SUCCESS) { + pCommandStatus->GeneralStatus = LongOpNvmStatus; + SetObjStatusForDimmWithErase(pCommandStatus, pDimms[Index], LongOpNvmStatus, TRUE); } - else - { - pCommandStatus->GeneralStatus = NvmStatus; - SetObjStatusForDimmWithErase(pCommandStatus, pDimms[Index], NvmStatus, TRUE); + else { + if (NvmStatus == NVM_SUCCESS) { + pCommandStatus->GeneralStatus = NVM_ERR_OPERATION_FAILED; + SetObjStatusForDimmWithErase(pCommandStatus, pDimms[Index], NVM_ERR_OPERATION_FAILED, TRUE); + } + else + { + pCommandStatus->GeneralStatus = NvmStatus; + SetObjStatusForDimmWithErase(pCommandStatus, pDimms[Index], NvmStatus, TRUE); + } } } else @@ -5533,6 +5551,64 @@ UpdateFw( return ReturnCode; } +/** + Examine a given DIMM to see if a long op is in progress and report it back + + @param[in] pDimm The dimm to check the status of + @param[out] pNvmStatus The status of the dimm's long op status. NVM_SUCCESS = No long op status is under way. + + @retval EFI_SUCCESS if the request for long op status was successful (whether a long op status is under way or not) + @retval EFI_... the error preventing the check for the long op status +**/ +EFI_STATUS +CheckForLongOpStatusInProgress( + IN DIMM *pDimm, + OUT NVM_STATUS *pNvmStatus +) +{ + EFI_STATUS ReturnCode = EFI_SUCCESS; + UINT8 LongOpStatusCode = 0; + PT_OUTPUT_PAYLOAD_FW_LONG_OP_STATUS LongOpStatus; + EFI_STATUS LongOpCheckRetCode = EFI_SUCCESS; + + NVDIMM_ENTRY(); + + if (pNvmStatus == NULL) { + ReturnCode = EFI_INVALID_PARAMETER; + goto Finish; + } + + *pNvmStatus = NVM_SUCCESS; + LongOpCheckRetCode = FwCmdGetLongOperationStatus(pDimm, &LongOpStatusCode, &LongOpStatus); + if (EFI_ERROR(LongOpCheckRetCode)) { + //fatal error + *pNvmStatus = NVM_ERR_UNKNOWN; + ReturnCode = LongOpCheckRetCode; + goto Finish; + } + else if (LongOpStatus.Status != FW_DEVICE_BUSY) { + //no long op in progress + goto Finish; + } + + if (LongOpStatus.CmdOpcode == PtGetFeatures && LongOpStatus.CmdSubcode == SubopAddressRangeScrub) { + *pNvmStatus = NVM_ERR_ARS_IN_PROGRESS; + } + else if (LongOpStatus.CmdOpcode == PtUpdateFw && LongOpStatus.CmdSubcode == SubopUpdateFw) { + *pNvmStatus = NVM_ERR_FWUPDATE_IN_PROGRESS; + } + else if (LongOpStatus.CmdOpcode == PtSetSecInfo && LongOpStatus.CmdSubcode == SubopOverwriteDimm) { + *pNvmStatus = NVM_ERR_OVERWRITE_DIMM_IN_PROGRESS; + } + else { + *pNvmStatus = NVM_ERR_UNKNOWN_LONG_OP_IN_PROGRESS; + } + +Finish: + NVDIMM_EXIT_I64(ReturnCode); + return ReturnCode; +} + /** Filter a list of dimms by a given socket and return an array of dimms that exist on a given socket diff --git a/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.h b/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.h index 5f0d6d3d..36e1d70b 100644 --- a/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.h +++ b/DcpmPkg/driver/Protocol/Driver/NvmDimmConfig.h @@ -1478,6 +1478,21 @@ VerifyTargetDimms( OUT COMMAND_STATUS *pCommandStatus ); +/** + Examine a given DIMM to see if a long op is in progress and report it back + + @param[in] pDimm The dimm to check the status of + @param[out] pNvmStatus The status of the dimm's long op status. NVM_SUCCESS = No long op status is under way. + + @retval EFI_SUCCESS if the request for long op status was successful (whether a long op status is under way or not) + @retval EFI_... the error preventing the check for the long op status +**/ +EFI_STATUS +CheckForLongOpStatusInProgress( + IN DIMM *pDimm, + OUT NVM_STATUS *pNvmStatus +); + // Debug Only #ifndef MDEPKG_NDEBUG