UfsPassThruDxe driver is used to produce EFI_EXT_SCSI_PASS_THRU protocol interface\r
for upper layer application to execute UFS-supported SCSI cmds.\r
\r
- Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2014 - 2019, Intel Corporation. All rights reserved.<BR>\r
SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
UINT8 *Remaining;\r
UINTN PrdtNumber;\r
\r
- if ((BufferSize & (BIT0 | BIT1)) != 0) {\r
- BufferSize &= ~(BIT0 | BIT1);\r
- DEBUG ((DEBUG_WARN, "UfsInitUtpPrdt: The BufferSize [%d] is not dword-aligned!\n", BufferSize));\r
- }\r
+ ASSERT (((UINTN)Buffer & (BIT0 | BIT1)) == 0);\r
+ ASSERT ((BufferSize & (BIT1 | BIT0)) == 0);\r
\r
if (BufferSize == 0) {\r
return EFI_SUCCESS;\r
}\r
\r
- ASSERT (((UINTN)Buffer & (BIT0 | BIT1)) == 0);\r
-\r
RemainingLen = BufferSize;\r
Remaining = Buffer;\r
PrdtNumber = (UINTN)DivU64x32 ((UINT64)BufferSize + UFS_MAX_DATA_LEN_PER_PRD - 1, UFS_MAX_DATA_LEN_PER_PRD);\r
return Status;\r
}\r
\r
- Nutrs = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
+ Nutrs = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
\r
for (Index = 0; Index < Nutrs; Index++) {\r
if ((Data & (BIT0 << Index)) == 0) {\r
return Status;\r
}\r
\r
+/**\r
+ Cleanup data buffers after data transfer. This function\r
+ also takes care to copy all data to user memory pool for\r
+ unaligned data transfers.\r
+\r
+ @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA\r
+ @param[in] TransReq Pointer to the transfer request\r
+**/\r
+VOID\r
+UfsReconcileDataTransferBuffer (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN UFS_PASS_THRU_TRANS_REQ *TransReq\r
+ )\r
+{\r
+ if (TransReq->DataBufMapping != NULL) {\r
+ Private->UfsHostController->Unmap (\r
+ Private->UfsHostController,\r
+ TransReq->DataBufMapping\r
+ );\r
+ }\r
+\r
+ //\r
+ // Check if unaligned transfer was performed. If it was and we read\r
+ // data from device copy memory to user data buffers before cleanup.\r
+ // The assumption is if auxiliary aligned data buffer is not NULL then\r
+ // unaligned transfer has been performed.\r
+ //\r
+ if (TransReq->AlignedDataBuf != NULL) {\r
+ if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
+ CopyMem (TransReq->Packet->InDataBuffer, TransReq->AlignedDataBuf, TransReq->Packet->InTransferLength);\r
+ }\r
+ //\r
+ // Wipe out the transfer buffer in case it contains sensitive data.\r
+ //\r
+ ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);\r
+ FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));\r
+ TransReq->AlignedDataBuf = NULL;\r
+ }\r
+}\r
+\r
+/**\r
+ Prepare data buffer for transfer.\r
+\r
+ @param[in] Private Pointer to the UFS_PASS_THRU_PRIVATE_DATA\r
+ @param[in, out] TransReq Pointer to the transfer request\r
+\r
+ @retval EFI_DEVICE_ERROR Failed to prepare buffer for transfer\r
+ @retval EFI_SUCCESS Buffer ready for transfer\r
+**/\r
+EFI_STATUS\r
+UfsPrepareDataTransferBuffer (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN OUT UFS_PASS_THRU_TRANS_REQ *TransReq\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ VOID *DataBuf;\r
+ UINT32 DataLen;\r
+ UINTN MapLength;\r
+ EFI_PHYSICAL_ADDRESS DataBufPhyAddr;\r
+ EDKII_UFS_HOST_CONTROLLER_OPERATION Flag;\r
+ UTP_TR_PRD *PrdtBase;\r
+\r
+ DataBufPhyAddr = 0;\r
+ DataBuf = NULL;\r
+\r
+ //\r
+ // For unaligned data transfers we allocate auxiliary DWORD aligned memory pool.\r
+ // When command is finished auxiliary memory pool is copied into actual user memory.\r
+ // This is requiered to assure data transfer safety(DWORD alignment required by UFS spec.)\r
+ //\r
+ if (TransReq->Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
+ if (((UINTN)TransReq->Packet->InDataBuffer % 4 != 0) || (TransReq->Packet->InTransferLength % 4 != 0)) {\r
+ DataLen = TransReq->Packet->InTransferLength + (4 - (TransReq->Packet->InTransferLength % 4));\r
+ DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);\r
+ if (DataBuf == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ ZeroMem (DataBuf, DataLen);\r
+ TransReq->AlignedDataBuf = DataBuf;\r
+ TransReq->AlignedDataBufSize = DataLen;\r
+ } else {\r
+ DataLen = TransReq->Packet->InTransferLength;\r
+ DataBuf = TransReq->Packet->InDataBuffer;\r
+ }\r
+ Flag = EdkiiUfsHcOperationBusMasterWrite;\r
+ } else {\r
+ if (((UINTN)TransReq->Packet->OutDataBuffer % 4 != 0) || (TransReq->Packet->OutTransferLength % 4 != 0)) {\r
+ DataLen = TransReq->Packet->OutTransferLength + (4 - (TransReq->Packet->OutTransferLength % 4));\r
+ DataBuf = AllocateAlignedPages (EFI_SIZE_TO_PAGES (DataLen), 4);\r
+ if (DataBuf == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ CopyMem (DataBuf, TransReq->Packet->OutDataBuffer, TransReq->Packet->OutTransferLength);\r
+ TransReq->AlignedDataBuf = DataBuf;\r
+ TransReq->AlignedDataBufSize = DataLen;\r
+ } else {\r
+ DataLen = TransReq->Packet->OutTransferLength;\r
+ DataBuf = TransReq->Packet->OutDataBuffer;\r
+ }\r
+ Flag = EdkiiUfsHcOperationBusMasterRead;\r
+ }\r
+\r
+ if (DataLen != 0) {\r
+ MapLength = DataLen;\r
+ Status = Private->UfsHostController->Map (\r
+ Private->UfsHostController,\r
+ Flag,\r
+ DataBuf,\r
+ &MapLength,\r
+ &DataBufPhyAddr,\r
+ &TransReq->DataBufMapping\r
+ );\r
+\r
+ if (EFI_ERROR (Status) || (DataLen != MapLength)) {\r
+ if (TransReq->AlignedDataBuf != NULL) {\r
+ //\r
+ // Wipe out the transfer buffer in case it contains sensitive data.\r
+ //\r
+ ZeroMem (TransReq->AlignedDataBuf, TransReq->AlignedDataBufSize);\r
+ FreeAlignedPages (TransReq->AlignedDataBuf, EFI_SIZE_TO_PAGES (TransReq->AlignedDataBufSize));\r
+ TransReq->AlignedDataBuf = NULL;\r
+ }\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Fill PRDT table of Command UPIU for executed SCSI cmd.\r
+ //\r
+ PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
+ ASSERT (PrdtBase != NULL);\r
+ UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.\r
\r
UTP_RESPONSE_UPIU *Response;\r
UINT16 SenseDataLen;\r
UINT32 ResTranCount;\r
- VOID *DataBuf;\r
- EFI_PHYSICAL_ADDRESS DataBufPhyAddr;\r
- UINT32 DataLen;\r
- UINTN MapLength;\r
- EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
- EDKII_UFS_HOST_CONTROLLER_OPERATION Flag;\r
- UTP_TR_PRD *PrdtBase;\r
EFI_TPL OldTpl;\r
UFS_PASS_THRU_TRANS_REQ *TransReq;\r
+ EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
\r
- TransReq = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));\r
+ TransReq = AllocateZeroPool (sizeof (UFS_PASS_THRU_TRANS_REQ));\r
if (TransReq == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
TransReq->Signature = UFS_PASS_THRU_TRANS_REQ_SIG;\r
TransReq->TimeoutRemain = Packet->Timeout;\r
- DataBufPhyAddr = 0;\r
+ TransReq->Packet = Packet;\r
+\r
UfsHc = Private->UfsHostController;\r
//\r
// Find out which slot of transfer request list is available.\r
\r
TransReq->CmdDescSize = TransReq->Trd->PrdtO * sizeof (UINT32) + TransReq->Trd->PrdtL * sizeof (UTP_TR_PRD);\r
\r
- if (Packet->DataDirection == EFI_EXT_SCSI_DATA_DIRECTION_READ) {\r
- DataBuf = Packet->InDataBuffer;\r
- DataLen = Packet->InTransferLength;\r
- Flag = EdkiiUfsHcOperationBusMasterWrite;\r
- } else {\r
- DataBuf = Packet->OutDataBuffer;\r
- DataLen = Packet->OutTransferLength;\r
- Flag = EdkiiUfsHcOperationBusMasterRead;\r
- }\r
-\r
- if (DataLen != 0) {\r
- MapLength = DataLen;\r
- Status = UfsHc->Map (\r
- UfsHc,\r
- Flag,\r
- DataBuf,\r
- &MapLength,\r
- &DataBufPhyAddr,\r
- &TransReq->DataBufMapping\r
- );\r
-\r
- if (EFI_ERROR (Status) || (DataLen != MapLength)) {\r
- goto Exit1;\r
- }\r
+ Status = UfsPrepareDataTransferBuffer (Private, TransReq);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit1;\r
}\r
- //\r
- // Fill PRDT table of Command UPIU for executed SCSI cmd.\r
- //\r
- PrdtBase = (UTP_TR_PRD*)((UINT8*)TransReq->CmdDescHost + ROUNDUP8 (sizeof (UTP_COMMAND_UPIU)) + ROUNDUP8 (sizeof (UTP_RESPONSE_UPIU)));\r
- ASSERT (PrdtBase != NULL);\r
- UfsInitUtpPrdt (PrdtBase, (VOID*)(UINTN)DataBufPhyAddr, DataLen);\r
\r
//\r
// Insert the async SCSI cmd to the Async I/O list\r
//\r
if (Event != NULL) {\r
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);\r
- TransReq->Packet = Packet;\r
TransReq->CallerEvent = Event;\r
InsertTailList (&Private->Queue, &TransReq->TransferList);\r
gBS->RestoreTPL (OldTpl);\r
\r
UfsStopExecCmd (Private, TransReq->Slot);\r
\r
- if (TransReq->DataBufMapping != NULL) {\r
- UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);\r
- }\r
+ UfsReconcileDataTransferBuffer (Private, TransReq);\r
\r
Exit1:\r
if (TransReq->CmdDescMapping != NULL) {\r
return Status;\r
}\r
\r
-\r
/**\r
- Sent UIC DME_LINKSTARTUP command to start the link startup procedure.\r
+ Send UIC command.\r
\r
- @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
- @param[in] UicOpcode The opcode of the UIC command.\r
- @param[in] Arg1 The value for 1st argument of the UIC command.\r
- @param[in] Arg2 The value for 2nd argument of the UIC command.\r
- @param[in] Arg3 The value for 3rd argument of the UIC command.\r
+ @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+ @param[in, out] UicCommand UIC command descriptor. On exit contains UIC command results.\r
\r
@return EFI_SUCCESS Successfully execute this UIC command and detect attached UFS device.\r
@return EFI_DEVICE_ERROR Fail to execute this UIC command and detect attached UFS device.\r
- @return EFI_NOT_FOUND The presence of the UFS device isn't detected.\r
\r
**/\r
EFI_STATUS\r
UfsExecUicCommands (\r
IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
- IN UINT8 UicOpcode,\r
- IN UINT32 Arg1,\r
- IN UINT32 Arg2,\r
- IN UINT32 Arg3\r
+ IN OUT EDKII_UIC_COMMAND *UicCommand\r
)\r
{\r
EFI_STATUS Status;\r
// only after all the UIC command argument registers (UICCMDARG1, UICCMDARG2 and UICCMDARG3)\r
// are set.\r
//\r
- Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, Arg1);\r
+ Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG1_OFFSET, UicCommand->Arg1);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, Arg2);\r
+ Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG2_OFFSET, UicCommand->Arg2);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, Arg3);\r
+ Status = UfsMmioWrite32 (Private, UFS_HC_UCMD_ARG3_OFFSET, UicCommand->Arg3);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
return Status;\r
}\r
\r
- Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, (UINT32)UicOpcode);\r
+ Status = UfsMmioWrite32 (Private, UFS_HC_UIC_CMD_OFFSET, UicCommand->Opcode);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
return Status;\r
}\r
\r
- if (UicOpcode != UfsUicDmeReset) {\r
- Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &Data);\r
+ if (UicCommand->Opcode != UfsUicDmeReset) {\r
+ Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG2_OFFSET, &UicCommand->Arg2);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- if ((Data & 0xFF) != 0) {\r
+ Status = UfsMmioRead32 (Private, UFS_HC_UCMD_ARG3_OFFSET, &UicCommand->Arg3);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ if ((UicCommand->Arg2 & 0xFF) != 0) {\r
DEBUG_CODE_BEGIN();\r
- DumpUicCmdExecResult (UicOpcode, (UINT8)(Data & 0xFF));\r
+ DumpUicCmdExecResult ((UINT8)UicCommand->Opcode, (UINT8)(UicCommand->Arg2 & 0xFF));\r
DEBUG_CODE_END();\r
return EFI_DEVICE_ERROR;\r
}\r
}\r
\r
- //\r
- // Check value of HCS.DP and make sure that there is a device attached to the Link.\r
- //\r
- Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- if ((Data & UFS_HC_HCS_DP) == 0) {\r
- Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- return EFI_NOT_FOUND;\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "UfsPassThruDxe: found a attached UFS device\n"));\r
-\r
return EFI_SUCCESS;\r
}\r
\r
BOOLEAN Is32BitAddr;\r
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;\r
\r
- if ((Private->Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {\r
+ if ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_64ADDR) == UFS_HC_CAP_64ADDR) {\r
Is32BitAddr = FALSE;\r
} else {\r
Is32BitAddr = TRUE;\r
IN UFS_PASS_THRU_PRIVATE_DATA *Private\r
)\r
{\r
- UINTN Retry;\r
- EFI_STATUS Status;\r
+ UINTN Retry;\r
+ EFI_STATUS Status;\r
+ UINT32 Data;\r
+ EDKII_UIC_COMMAND LinkStartupCommand;\r
\r
//\r
// Start UFS device detection.\r
// Try up to 3 times for establishing data link with device.\r
//\r
for (Retry = 0; Retry < 3; Retry++) {\r
- Status = UfsExecUicCommands (Private, UfsUicDmeLinkStartup, 0, 0, 0);\r
- if (!EFI_ERROR (Status)) {\r
- break;\r
+ LinkStartupCommand.Opcode = UfsUicDmeLinkStartup;\r
+ LinkStartupCommand.Arg1 = 0;\r
+ LinkStartupCommand.Arg2 = 0;\r
+ LinkStartupCommand.Arg3 = 0;\r
+ Status = UfsExecUicCommands (Private, &LinkStartupCommand);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
}\r
\r
- if (Status == EFI_NOT_FOUND) {\r
- continue;\r
+ Status = UfsMmioRead32 (Private, UFS_HC_STATUS_OFFSET, &Data);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
}\r
\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- if (Retry == 3) {\r
- return EFI_NOT_FOUND;\r
+ if ((Data & UFS_HC_HCS_DP) == 0) {\r
+ Status = UfsWaitMemSet (Private, UFS_HC_IS_OFFSET, UFS_HC_IS_ULSS, UFS_HC_IS_ULSS, UFS_TIMEOUT);\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ } else {\r
+ return EFI_SUCCESS;\r
+ }\r
}\r
\r
- return EFI_SUCCESS;\r
+ return EFI_NOT_FOUND;\r
}\r
\r
/**\r
IN UFS_PASS_THRU_PRIVATE_DATA *Private\r
)\r
{\r
- UINT32 Data;\r
UINT8 Nutmrs;\r
VOID *CmdDescHost;\r
EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;\r
CmdDescMapping = NULL;\r
CmdDescPhyAddr = 0;\r
\r
- Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Private->Capabilities = Data;\r
-\r
//\r
// Allocate and initialize UTP Task Management Request List.\r
//\r
- Nutmrs = (UINT8) (RShiftU64 ((Private->Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);\r
+ Nutmrs = (UINT8) (RShiftU64 ((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTMRS), 16) + 1);\r
Status = UfsAllocateAlignCommonBuffer (Private, Nutmrs * sizeof (UTP_TMRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
IN UFS_PASS_THRU_PRIVATE_DATA *Private\r
)\r
{\r
- UINT32 Data;\r
UINT8 Nutrs;\r
VOID *CmdDescHost;\r
EFI_PHYSICAL_ADDRESS CmdDescPhyAddr;\r
CmdDescMapping = NULL;\r
CmdDescPhyAddr = 0;\r
\r
- Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Private->Capabilities = Data;\r
-\r
//\r
// Allocate and initialize UTP Transfer Request List.\r
//\r
- Nutrs = (UINT8)((Private->Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
+ Nutrs = (UINT8)((Private->UfsHcInfo.Capabilities & UFS_HC_CAP_NUTRS) + 1);\r
Status = UfsAllocateAlignCommonBuffer (Private, Nutrs * sizeof (UTP_TRD), &CmdDescHost, &CmdDescPhyAddr, &CmdDescMapping);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
return EFI_SUCCESS;\r
}\r
\r
-\r
/**\r
Internal helper function which will signal the caller event and clean up\r
resources.\r
\r
UfsStopExecCmd (Private, TransReq->Slot);\r
\r
- if (TransReq->DataBufMapping != NULL) {\r
- UfsHc->Unmap (UfsHc, TransReq->DataBufMapping);\r
- }\r
+ UfsReconcileDataTransferBuffer (Private, TransReq);\r
\r
if (TransReq->CmdDescMapping != NULL) {\r
UfsHc->Unmap (UfsHc, TransReq->CmdDescMapping);\r
}\r
}\r
\r
+/**\r
+ Initializes UfsHcInfo field in private data.\r
+\r
+ @param[in] Private Pointer to host controller private data.\r
+\r
+ @retval EFI_SUCCESS UfsHcInfo initialized successfully.\r
+ @retval Others Failed to initalize UfsHcInfo.\r
+**/\r
+EFI_STATUS\r
+GetUfsHcInfo (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ UINT32 Data;\r
+ EFI_STATUS Status;\r
+\r
+ Status = UfsMmioRead32 (Private, UFS_HC_VER_OFFSET, &Data);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Private->UfsHcInfo.Version = Data;\r
+\r
+ Status = UfsMmioRead32 (Private, UFS_HC_CAP_OFFSET, &Data);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Private->UfsHcInfo.Capabilities = Data;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r