--- /dev/null
+/** @file\r
+ The implementation of the EFI UFS Device Config Protocol.\r
+\r
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+ This program and the accompanying materials\r
+ are licensed and made available under the terms and conditions of the BSD License\r
+ which accompanies this distribution. The full text of the license may be found at\r
+ http://opensource.org/licenses/bsd-license.php\r
+\r
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "UfsPassThru.h"\r
+\r
+/**\r
+ Read or write specified device descriptor of a UFS device.\r
+\r
+ The function is used to read/write UFS device descriptors. The consumer of this API is\r
+ responsible for allocating the data buffer pointed by Descriptor.\r
+\r
+ @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] DescId The ID of device descriptor.\r
+ @param[in] Index The Index of device descriptor.\r
+ @param[in] Selector The Selector of device descriptor.\r
+ @param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
+ @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes,\r
+ of the data buffer specified by Descriptor. On output, the number\r
+ of bytes that were actually transferred.\r
+\r
+ @retval EFI_SUCCESS The device descriptor is read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Descriptor is NULL or DescSize is NULL.\r
+ DescId, Index and Selector are invalid combination to point to a\r
+ type of UFS device descriptor.\r
+ @retval EFI_DEVICE_ERROR The device descriptor is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsDescriptor (\r
+ IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 DescId,\r
+ IN UINT8 Index,\r
+ IN UINT8 Selector,\r
+ IN OUT UINT8 *Descriptor,\r
+ IN OUT UINT32 *DescSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UFS_PASS_THRU_PRIVATE_DATA *Private;\r
+\r
+ Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG (This);\r
+\r
+ if ((This == NULL) || (Descriptor == NULL) || (DescSize == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = UfsRwDeviceDesc (\r
+ Private,\r
+ Read,\r
+ DescId,\r
+ Index,\r
+ Selector,\r
+ Descriptor,\r
+ DescSize\r
+ );\r
+ if (Status == EFI_TIMEOUT) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Read or write specified flag of a UFS device.\r
+\r
+ The function is used to read/write UFS flag descriptors. The consumer of this API is responsible\r
+ for allocating the buffer pointed by Flag. The buffer size is 1 byte as UFS flag descriptor is\r
+ just a single Boolean value that represents a TRUE or FALSE, '0' or '1', ON or OFF type of value.\r
+\r
+ @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] FlagId The ID of flag to be read or written.\r
+ @param[in, out] Flag The buffer to set or clear flag.\r
+\r
+ @retval EFI_SUCCESS The flag descriptor is set/clear successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Flag is NULL.\r
+ FlagId is an invalid UFS flag ID.\r
+ @retval EFI_DEVICE_ERROR The flag is not set/clear successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsFlag (\r
+ IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 FlagId,\r
+ IN OUT UINT8 *Flag\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UFS_PASS_THRU_PRIVATE_DATA *Private;\r
+\r
+ Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG (This);\r
+\r
+ if ((This == NULL) || (Flag == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = UfsRwFlags (Private, Read, FlagId, Flag);\r
+ if (Status == EFI_TIMEOUT) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Read or write specified attribute of a UFS device.\r
+\r
+ The function is used to read/write UFS attributes. The consumer of this API is responsible for\r
+ allocating the data buffer pointed by Attribute.\r
+\r
+ @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] AttrId The ID of Attribute.\r
+ @param[in] Index The Index of Attribute.\r
+ @param[in] Selector The Selector of Attribute.\r
+ @param[in, out] Attribute The buffer of Attribute to be read or written.\r
+ @param[in, out] AttrSize The size of Attribute buffer. On input, the size, in bytes, of the\r
+ data buffer specified by Attribute. On output, the number of bytes\r
+ that were actually transferred.\r
+\r
+ @retval EFI_SUCCESS The attribute is read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Attribute is NULL or AttrSize is NULL.\r
+ AttrId, Index and Selector are invalid combination to point to a\r
+ type of UFS attribute.\r
+ @retval EFI_DEVICE_ERROR The attribute is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsAttribute (\r
+ IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 AttrId,\r
+ IN UINT8 Index,\r
+ IN UINT8 Selector,\r
+ IN OUT UINT8 *Attribute,\r
+ IN OUT UINT32 *AttrSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UFS_PASS_THRU_PRIVATE_DATA *Private;\r
+ UINT32 Attribute32;\r
+\r
+ Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG (This);\r
+ Attribute32 = 0;\r
+\r
+ if ((This == NULL) || (Attribute == NULL) || (AttrSize == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // According to UFS Version 2.1 Spec (JESD220C) Section 14.3, the size of a attribute will not\r
+ // exceed 32-bit.\r
+ //\r
+ if (*AttrSize > 4) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (!Read) {\r
+ CopyMem (&Attribute32, Attribute, *AttrSize);\r
+ }\r
+\r
+ Status = UfsRwAttributes (\r
+ Private,\r
+ Read,\r
+ AttrId,\r
+ Index,\r
+ Selector,\r
+ &Attribute32\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ if (Read) {\r
+ CopyMem (Attribute, &Attribute32, *AttrSize);\r
+ }\r
+ } else {\r
+ *AttrSize = 0;\r
+ if (Status == EFI_TIMEOUT) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+ return Status;\r
+}\r
UfsPassThruResetTargetLun,\r
UfsPassThruGetNextTarget\r
},\r
+ { // UfsDevConfig\r
+ UfsRwUfsDescriptor,\r
+ UfsRwUfsFlag,\r
+ UfsRwUfsAttribute\r
+ },\r
0, // UfsHostController\r
0, // UfsHcBase\r
0, // Capabilities\r
UINTN UfsHcBase;\r
UINT32 Index;\r
UFS_UNIT_DESC UnitDescriptor;\r
+ UINT32 UnitDescriptorSize;\r
\r
Status = EFI_SUCCESS;\r
UfsHc = NULL;\r
// Check if 8 common luns are active and set corresponding bit mask.\r
// TODO: Parse device descriptor to decide if exposing RPMB LUN to upper layer for authentication access.\r
//\r
+ UnitDescriptorSize = sizeof (UFS_UNIT_DESC);\r
for (Index = 0; Index < 8; Index++) {\r
- Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8) Index, 0, &UnitDescriptor, sizeof (UFS_UNIT_DESC));\r
+ Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8) Index, 0, &UnitDescriptor, &UnitDescriptorSize);\r
if (EFI_ERROR (Status)) {\r
DEBUG ((DEBUG_ERROR, "Failed to read unit descriptor, index = %X, status = %r\n", Index, Status));\r
continue;\r
goto Error;\r
}\r
\r
- Status = gBS->InstallProtocolInterface (\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
&Controller,\r
&gEfiExtScsiPassThruProtocolGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &(Private->ExtScsiPassThru)\r
+ &(Private->ExtScsiPassThru),\r
+ &gEfiUfsDeviceConfigProtocolGuid,\r
+ &(Private->UfsDevConfig),\r
+ NULL\r
);\r
ASSERT_EFI_ERROR (Status);\r
\r
}\r
}\r
\r
- Status = gBS->UninstallProtocolInterface (\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
Controller,\r
&gEfiExtScsiPassThruProtocolGuid,\r
- &(Private->ExtScsiPassThru)\r
+ &(Private->ExtScsiPassThru),\r
+ &gEfiUfsDeviceConfigProtocolGuid,\r
+ &(Private->UfsDevConfig),\r
+ NULL\r
);\r
\r
if (EFI_ERROR (Status)) {\r
#include <Uefi.h>\r
\r
#include <Protocol/ScsiPassThruExt.h>\r
+#include <Protocol/UfsDeviceConfig.h>\r
#include <Protocol/UfsHostController.h>\r
\r
#include <Library/DebugLib.h>\r
EFI_HANDLE Handle;\r
EFI_EXT_SCSI_PASS_THRU_MODE ExtScsiPassThruMode;\r
EFI_EXT_SCSI_PASS_THRU_PROTOCOL ExtScsiPassThru;\r
+ EFI_UFS_DEVICE_CONFIG_PROTOCOL UfsDevConfig;\r
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHostController;\r
UINTN UfsHcBase;\r
UINT32 Capabilities;\r
UFS_PASS_THRU_SIG \\r
)\r
\r
+#define UFS_PASS_THRU_PRIVATE_DATA_FROM_DEV_CONFIG(a) \\r
+ CR (a, \\r
+ UFS_PASS_THRU_PRIVATE_DATA, \\r
+ UfsDevConfig, \\r
+ UFS_PASS_THRU_SIG \\r
+ )\r
+\r
typedef struct _UFS_DEVICE_MANAGEMENT_REQUEST_PACKET {\r
UINT64 Timeout;\r
VOID *DataBuffer;\r
OUT UINT8 *Value\r
);\r
\r
+/**\r
+ Read or write specified flag of a UFS device.\r
+\r
+ @param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] FlagId The ID of flag to be read or written.\r
+ @param[in, out] Value The value to set or clear flag.\r
+\r
+ @retval EFI_SUCCESS The flag was read/written successfully.\r
+ @retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the flag.\r
+ @retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the flag.\r
+\r
+**/\r
+EFI_STATUS\r
+UfsRwFlags (\r
+ IN UFS_PASS_THRU_PRIVATE_DATA *Private,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 FlagId,\r
+ IN OUT UINT8 *Value\r
+ );\r
+\r
/**\r
Read or write specified device descriptor of a UFS device.\r
\r
@param[in] Index The Index of device descriptor.\r
@param[in] Selector The Selector of device descriptor.\r
@param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
- @param[in] DescSize The size of device descriptor buffer.\r
+ @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes,\r
+ of the data buffer specified by Descriptor. On output, the number\r
+ of bytes that were actually transferred.\r
\r
@retval EFI_SUCCESS The device descriptor was read/written successfully.\r
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
IN UINT8 Index,\r
IN UINT8 Selector,\r
IN OUT VOID *Descriptor,\r
- IN UINT32 DescSize\r
+ IN OUT UINT32 *DescSize\r
);\r
\r
/**\r
IN UFS_PASS_THRU_TRANS_REQ *TransReq\r
);\r
\r
+/**\r
+ Read or write specified device descriptor of a UFS device.\r
+\r
+ The function is used to read/write UFS device descriptors. The consumer of this API is\r
+ responsible for allocating the data buffer pointed by Descriptor.\r
+\r
+ @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] DescId The ID of device descriptor.\r
+ @param[in] Index The Index of device descriptor.\r
+ @param[in] Selector The Selector of device descriptor.\r
+ @param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
+ @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes,\r
+ of the data buffer specified by Descriptor. On output, the number\r
+ of bytes that were actually transferred.\r
+\r
+ @retval EFI_SUCCESS The device descriptor is read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Descriptor is NULL or DescSize is NULL.\r
+ DescId, Index and Selector are invalid combination to point to a\r
+ type of UFS device descriptor.\r
+ @retval EFI_DEVICE_ERROR The device descriptor is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsDescriptor (\r
+ IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 DescId,\r
+ IN UINT8 Index,\r
+ IN UINT8 Selector,\r
+ IN OUT UINT8 *Descriptor,\r
+ IN OUT UINT32 *DescSize\r
+ );\r
+\r
+/**\r
+ Read or write specified flag of a UFS device.\r
+\r
+ The function is used to read/write UFS flag descriptors. The consumer of this API is responsible\r
+ for allocating the buffer pointed by Flag. The buffer size is 1 byte as UFS flag descriptor is\r
+ just a single Boolean value that represents a TRUE or FALSE, '0' or '1', ON or OFF type of value.\r
+\r
+ @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] FlagId The ID of flag to be read or written.\r
+ @param[in, out] Flag The buffer to set or clear flag.\r
+\r
+ @retval EFI_SUCCESS The flag descriptor is set/clear successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Flag is NULL.\r
+ FlagId is an invalid UFS flag ID.\r
+ @retval EFI_DEVICE_ERROR The flag is not set/clear successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsFlag (\r
+ IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 FlagId,\r
+ IN OUT UINT8 *Flag\r
+ );\r
+\r
+/**\r
+ Read or write specified attribute of a UFS device.\r
+\r
+ The function is used to read/write UFS attributes. The consumer of this API is responsible for\r
+ allocating the data buffer pointed by Attribute.\r
+\r
+ @param[in] This The pointer to the EFI_UFS_DEVICE_CONFIG_PROTOCOL instance.\r
+ @param[in] Read The boolean variable to show r/w direction.\r
+ @param[in] AttrId The ID of Attribute.\r
+ @param[in] Index The Index of Attribute.\r
+ @param[in] Selector The Selector of Attribute.\r
+ @param[in, out] Attribute The buffer of Attribute to be read or written.\r
+ @param[in, out] AttrSize The size of Attribute buffer. On input, the size, in bytes, of the\r
+ data buffer specified by Attribute. On output, the number of bytes\r
+ that were actually transferred.\r
+\r
+ @retval EFI_SUCCESS The attribute is read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER This is NULL or Attribute is NULL or AttrSize is NULL.\r
+ AttrId, Index and Selector are invalid combination to point to a\r
+ type of UFS attribute.\r
+ @retval EFI_DEVICE_ERROR The attribute is not read/written successfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+UfsRwUfsAttribute (\r
+ IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This,\r
+ IN BOOLEAN Read,\r
+ IN UINT8 AttrId,\r
+ IN UINT8 Index,\r
+ IN UINT8 Selector,\r
+ IN OUT UINT8 *Attribute,\r
+ IN OUT UINT32 *AttrSize\r
+ );\r
+\r
extern EFI_COMPONENT_NAME_PROTOCOL gUfsPassThruComponentName;\r
extern EFI_COMPONENT_NAME2_PROTOCOL gUfsPassThruComponentName2;\r
extern EFI_DRIVER_BINDING_PROTOCOL gUfsPassThruDriverBinding;\r
## @file\r
# Description file for the Universal Flash Storage (UFS) Pass Thru driver.\r
#\r
-# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>\r
+# Copyright (c) 2014 - 2017, Intel Corporation. All rights reserved.<BR>\r
#\r
# This program and the accompanying materials\r
# are licensed and made available under the terms and conditions of the BSD License\r
\r
[Sources]\r
ComponentName.c\r
+ UfsDevConfigProtocol.c\r
UfsPassThru.c\r
UfsPassThru.h\r
UfsPassThruHci.c\r
\r
[Protocols]\r
gEfiExtScsiPassThruProtocolGuid ## BY_START\r
+ gEfiUfsDeviceConfigProtocolGuid ## BY_START\r
gEdkiiUfsHostControllerProtocolGuid ## TO_START\r
\r
[UserExtensions.TianoCore."ExtraFiles"]\r
@param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_REQUEST_PACKET.\r
\r
@retval EFI_SUCCESS The device descriptor was read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+ combination to point to a type of UFS device descriptor.\r
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
\r
if (Trd->Ocs != 0 || QueryResp->QueryResp != UfsUtpQueryResponseSuccess) {\r
DEBUG ((DEBUG_ERROR, "Failed to send query request, OCS = %X, QueryResp = %X\n", Trd->Ocs, QueryResp->QueryResp));\r
DumpQueryResponseResult (QueryResp->QueryResp);\r
- Status = EFI_DEVICE_ERROR;\r
+\r
+ if ((QueryResp->QueryResp == UfsUtpQueryResponseInvalidSelector) ||\r
+ (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIndex) ||\r
+ (QueryResp->QueryResp == UfsUtpQueryResponseInvalidIdn)) {\r
+ Status = EFI_INVALID_PARAMETER;\r
+ } else {\r
+ Status = EFI_DEVICE_ERROR;\r
+ }\r
goto Exit;\r
}\r
\r
@param[in] Packet Pointer to the UFS_DEVICE_MANAGEMENT_PACKET.\r
\r
@retval EFI_SUCCESS The device responded correctly to the Query request.\r
+ @retval EFI_INVALID_PARAMETER The DescId, Index and Selector fields in Packet are invalid\r
+ combination to point to a type of UFS device descriptor.\r
@retval EFI_DEVICE_ERROR A device error occurred while waiting for the response from the device.\r
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of the operation.\r
\r
@param[in] Index The Index of device descriptor.\r
@param[in] Selector The Selector of device descriptor.\r
@param[in, out] Descriptor The buffer of device descriptor to be read or written.\r
- @param[in] DescSize The size of device descriptor buffer.\r
+ @param[in, out] DescSize The size of device descriptor buffer. On input, the size, in bytes,\r
+ of the data buffer specified by Descriptor. On output, the number\r
+ of bytes that were actually transferred.\r
\r
@retval EFI_SUCCESS The device descriptor was read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER DescId, Index and Selector are invalid combination to point to a\r
+ type of UFS device descriptor.\r
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.\r
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.\r
\r
IN UINT8 Index,\r
IN UINT8 Selector,\r
IN OUT VOID *Descriptor,\r
- IN UINT32 DescSize\r
+ IN OUT UINT32 *DescSize\r
)\r
{\r
UFS_DEVICE_MANAGEMENT_REQUEST_PACKET Packet;\r
+ EFI_STATUS Status;\r
+\r
+ if (DescSize == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
ZeroMem (&Packet, sizeof (UFS_DEVICE_MANAGEMENT_REQUEST_PACKET));\r
\r
Packet.Opcode = UtpQueryFuncOpcodeWrDesc;\r
}\r
Packet.DataBuffer = Descriptor;\r
- Packet.TransferLength = DescSize;\r
+ Packet.TransferLength = *DescSize;\r
Packet.DescId = DescId;\r
Packet.Index = Index;\r
Packet.Selector = Selector;\r
Packet.Timeout = UFS_TIMEOUT;\r
\r
- return UfsSendDmRequest (Private, &Packet);\r
+ Status = UfsSendDmRequest (Private, &Packet);\r
+ if (EFI_ERROR (Status)) {\r
+ *DescSize = 0;\r
+ } else {\r
+ *DescSize = Packet.TransferLength;\r
+ }\r
+\r
+ return Status;\r
}\r
\r
/**\r
@param[in, out] Attributes The value of Attribute to be read or written.\r
\r
@retval EFI_SUCCESS The Attribute was read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER AttrId, Index and Selector are invalid combination to point to a\r
+ type of UFS device descriptor.\r
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the Attribute.\r
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the Attribute.\r
\r
@param[in, out] Value The value to set or clear flag.\r
\r
@retval EFI_SUCCESS The flag was read/written successfully.\r
+ @retval EFI_INVALID_PARAMETER FlagId is an invalid UFS flag ID.\r
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the flag.\r
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the flag.\r
\r