Home | History | Annotate | Download | only in UfsPassThruDxe
      1 /** @file
      2 
      3   Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
      4   This program and the accompanying materials
      5   are licensed and made available under the terms and conditions of the BSD License
      6   which accompanies this distribution.  The full text of the license may be found at
      7   http://opensource.org/licenses/bsd-license.php
      8 
      9   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 **/
     13 
     14 #include "UfsPassThru.h"
     15 
     16 //
     17 // Template for Ufs Pass Thru private data.
     18 //
     19 UFS_PASS_THRU_PRIVATE_DATA gUfsPassThruTemplate = {
     20   UFS_PASS_THRU_SIG,              // Signature
     21   NULL,                           // Handle
     22   {                               // ExtScsiPassThruMode
     23     0xFFFFFFFF,
     24     EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL | EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO,
     25     sizeof (UINTN)
     26   },
     27   {                               // ExtScsiPassThru
     28     NULL,
     29     UfsPassThruPassThru,
     30     UfsPassThruGetNextTargetLun,
     31     UfsPassThruBuildDevicePath,
     32     UfsPassThruGetTargetLun,
     33     UfsPassThruResetChannel,
     34     UfsPassThruResetTargetLun,
     35     UfsPassThruGetNextTarget
     36   },
     37   0,                              // UfsHostController
     38   0,                              // UfsHcBase
     39   0,                              // Capabilities
     40   0,                              // TaskTag
     41   0,                              // UtpTrlBase
     42   0,                              // Nutrs
     43   0,                              // TrlMapping
     44   0,                              // UtpTmrlBase
     45   0,                              // Nutmrs
     46   0,                              // TmrlMapping
     47   {                               // Luns
     48     {
     49       UFS_LUN_0,                      // Ufs Common Lun 0
     50       UFS_LUN_1,                      // Ufs Common Lun 1
     51       UFS_LUN_2,                      // Ufs Common Lun 2
     52       UFS_LUN_3,                      // Ufs Common Lun 3
     53       UFS_LUN_4,                      // Ufs Common Lun 4
     54       UFS_LUN_5,                      // Ufs Common Lun 5
     55       UFS_LUN_6,                      // Ufs Common Lun 6
     56       UFS_LUN_7,                      // Ufs Common Lun 7
     57       UFS_WLUN_REPORT_LUNS,           // Ufs Reports Luns Well Known Lun
     58       UFS_WLUN_UFS_DEV,               // Ufs Device Well Known Lun
     59       UFS_WLUN_BOOT,                  // Ufs Boot Well Known Lun
     60       UFS_WLUN_RPMB                   // RPMB Well Known Lun
     61     },
     62     0x0000,                           // By default don't expose any Luns.
     63     0x0
     64   },
     65   NULL,                           // TimerEvent
     66   {                               // Queue
     67     NULL,
     68     NULL
     69   }
     70 };
     71 
     72 EFI_DRIVER_BINDING_PROTOCOL gUfsPassThruDriverBinding = {
     73   UfsPassThruDriverBindingSupported,
     74   UfsPassThruDriverBindingStart,
     75   UfsPassThruDriverBindingStop,
     76   0x10,
     77   NULL,
     78   NULL
     79 };
     80 
     81 UFS_DEVICE_PATH    mUfsDevicePathTemplate = {
     82   {
     83     MESSAGING_DEVICE_PATH,
     84     MSG_UFS_DP,
     85     {
     86       (UINT8) (sizeof (UFS_DEVICE_PATH)),
     87       (UINT8) ((sizeof (UFS_DEVICE_PATH)) >> 8)
     88     }
     89   },
     90   0,
     91   0
     92 };
     93 
     94 UINT8 mUfsTargetId[TARGET_MAX_BYTES];
     95 
     96 /**
     97   Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function
     98   supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the
     99   nonblocking I/O functionality is optional.
    100 
    101   @param  This    A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
    102   @param  Target  The Target is an array of size TARGET_MAX_BYTES and it represents
    103                   the id of the SCSI device to send the SCSI Request Packet. Each
    104                   transport driver may choose to utilize a subset of this size to suit the needs
    105                   of transport target representation. For example, a Fibre Channel driver
    106                   may use only 8 bytes (WWN) to represent an FC target.
    107   @param  Lun     The LUN of the SCSI device to send the SCSI Request Packet.
    108   @param  Packet  A pointer to the SCSI Request Packet to send to the SCSI device
    109                   specified by Target and Lun.
    110   @param  Event   If nonblocking I/O is not supported then Event is ignored, and blocking
    111                   I/O is performed. If Event is NULL, then blocking I/O is performed. If
    112                   Event is not NULL and non blocking I/O is supported, then
    113                   nonblocking I/O is performed, and Event will be signaled when the
    114                   SCSI Request Packet completes.
    115 
    116   @retval EFI_SUCCESS           The SCSI Request Packet was sent by the host. For bi-directional
    117                                 commands, InTransferLength bytes were transferred from
    118                                 InDataBuffer. For write and bi-directional commands,
    119                                 OutTransferLength bytes were transferred by
    120                                 OutDataBuffer.
    121   @retval EFI_BAD_BUFFER_SIZE   The SCSI Request Packet was not executed. The number of bytes that
    122                                 could be transferred is returned in InTransferLength. For write
    123                                 and bi-directional commands, OutTransferLength bytes were
    124                                 transferred by OutDataBuffer.
    125   @retval EFI_NOT_READY         The SCSI Request Packet could not be sent because there are too many
    126                                 SCSI Request Packets already queued. The caller may retry again later.
    127   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to send the SCSI Request
    128                                 Packet.
    129   @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid.
    130   @retval EFI_UNSUPPORTED       The command described by the SCSI Request Packet is not supported
    131                                 by the host adapter. This includes the case of Bi-directional SCSI
    132                                 commands not supported by the implementation. The SCSI Request
    133                                 Packet was not sent, so no additional status information is available.
    134   @retval EFI_TIMEOUT           A timeout occurred while waiting for the SCSI Request Packet to execute.
    135 
    136 **/
    137 EFI_STATUS
    138 EFIAPI
    139 UfsPassThruPassThru (
    140   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL                    *This,
    141   IN UINT8                                              *Target,
    142   IN UINT64                                             Lun,
    143   IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET     *Packet,
    144   IN EFI_EVENT                                          Event OPTIONAL
    145   )
    146 {
    147   EFI_STATUS                      Status;
    148   UFS_PASS_THRU_PRIVATE_DATA      *Private;
    149   UINT8                           UfsLun;
    150   UINT16                          Index;
    151 
    152   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
    153 
    154   if ((Packet == NULL) || (Packet->Cdb == NULL)) {
    155     return EFI_INVALID_PARAMETER;
    156   }
    157 
    158   //
    159   // Don't support variable length CDB
    160   //
    161   if ((Packet->CdbLength != 6) && (Packet->CdbLength != 10) &&
    162       (Packet->CdbLength != 12) && (Packet->CdbLength != 16)) {
    163     return EFI_INVALID_PARAMETER;
    164   }
    165 
    166   if ((Packet->SenseDataLength != 0) && (Packet->SenseData == NULL)) {
    167     return EFI_INVALID_PARAMETER;
    168   }
    169 
    170   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->InDataBuffer, This->Mode->IoAlign)) {
    171     return EFI_INVALID_PARAMETER;
    172   }
    173 
    174   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->OutDataBuffer, This->Mode->IoAlign)) {
    175     return EFI_INVALID_PARAMETER;
    176   }
    177 
    178   if ((This->Mode->IoAlign > 1) && !IS_ALIGNED(Packet->SenseData, This->Mode->IoAlign)) {
    179     return EFI_INVALID_PARAMETER;
    180   }
    181 
    182   //
    183   // For UFS 2.0 compatible device, 0 is always used to represent the location of the UFS device.
    184   //
    185   SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
    186   if ((Target == NULL) || (CompareMem(Target, mUfsTargetId, TARGET_MAX_BYTES) != 0)) {
    187     return EFI_INVALID_PARAMETER;
    188   }
    189 
    190   //
    191   // UFS 2.0 spec Section 10.6.7 - Translation of 8-bit UFS LUN to 64-bit SCSI LUN Address
    192   // 0xC1 in the first 8 bits of the 64-bit address indicates a well known LUN address in the SAM SCSI format.
    193   // The second 8 bits of the 64-bit address saves the corresponding 8-bit UFS LUN.
    194   //
    195   if ((UINT8)Lun == UFS_WLUN_PREFIX) {
    196     UfsLun = BIT7 | (((UINT8*)&Lun)[1] & 0xFF);
    197   } else if ((UINT8)Lun == 0) {
    198     UfsLun = ((UINT8*)&Lun)[1] & 0xFF;
    199   } else {
    200     return EFI_INVALID_PARAMETER;
    201   }
    202 
    203   for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
    204     if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
    205       continue;
    206     }
    207 
    208     if (Private->Luns.Lun[Index] == UfsLun) {
    209       break;
    210     }
    211   }
    212 
    213   if (Index == UFS_MAX_LUNS) {
    214     return EFI_INVALID_PARAMETER;
    215   }
    216 
    217   Status = UfsExecScsiCmds (Private, UfsLun, Packet, Event);
    218 
    219   return Status;
    220 }
    221 
    222 /**
    223   Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These
    224   can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
    225   Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the
    226   Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI
    227   channel.
    228 
    229   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
    230   @param  Target On input, a pointer to the Target ID (an array of size
    231                  TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
    232                  On output, a pointer to the Target ID (an array of
    233                  TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
    234                  channel. An input value of 0xF(all bytes in the array are 0xF) in the
    235                  Target array retrieves the Target ID of the first SCSI device present on a
    236                  SCSI channel.
    237   @param  Lun    On input, a pointer to the LUN of a SCSI device present on the SCSI
    238                  channel. On output, a pointer to the LUN of the next SCSI device present
    239                  on a SCSI channel.
    240 
    241   @retval EFI_SUCCESS           The Target ID and LUN of the next SCSI device on the SCSI
    242                                 channel was returned in Target and Lun.
    243   @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were
    244                                 not returned on a previous call to GetNextTargetLun().
    245   @retval EFI_NOT_FOUND         There are no more SCSI devices on this SCSI channel.
    246 
    247 **/
    248 EFI_STATUS
    249 EFIAPI
    250 UfsPassThruGetNextTargetLun (
    251   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    252   IN OUT UINT8                           **Target,
    253   IN OUT UINT64                          *Lun
    254   )
    255 {
    256   UFS_PASS_THRU_PRIVATE_DATA      *Private;
    257   UINT8                           UfsLun;
    258   UINT16                          Index;
    259   UINT16                          Next;
    260 
    261   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
    262 
    263   if (Target == NULL || Lun == NULL) {
    264     return EFI_INVALID_PARAMETER;
    265   }
    266 
    267   if (*Target == NULL) {
    268     return EFI_INVALID_PARAMETER;
    269   }
    270 
    271   UfsLun = 0;
    272   SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0xFF);
    273   if (CompareMem (*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
    274     //
    275     // If the array is all 0xFF's, return the first exposed Lun to caller.
    276     //
    277     SetMem (*Target, TARGET_MAX_BYTES, 0x00);
    278     for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
    279       if ((Private->Luns.BitMask & (BIT0 << Index)) != 0) {
    280         UfsLun = Private->Luns.Lun[Index];
    281         break;
    282       }
    283     }
    284     if (Index != UFS_MAX_LUNS) {
    285       *Lun = 0;
    286       if ((UfsLun & BIT7) == BIT7) {
    287         ((UINT8*)Lun)[0] = UFS_WLUN_PREFIX;
    288         ((UINT8*)Lun)[1] = UfsLun & ~BIT7;
    289       } else {
    290         ((UINT8*)Lun)[1] = UfsLun;
    291       }
    292       return EFI_SUCCESS;
    293     } else {
    294       return EFI_NOT_FOUND;
    295     }
    296   }
    297 
    298   SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
    299   if (CompareMem (*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
    300     if (((UINT8*)Lun)[0] == UFS_WLUN_PREFIX) {
    301       UfsLun = BIT7 | (((UINT8*)Lun)[1] & 0xFF);
    302     } else if (((UINT8*)Lun)[0] == 0) {
    303       UfsLun = ((UINT8*)Lun)[1] & 0xFF;
    304     } else {
    305       return EFI_NOT_FOUND;
    306     }
    307 
    308     for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
    309       if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
    310         continue;
    311       }
    312 
    313       if (Private->Luns.Lun[Index] != UfsLun) {
    314         continue;
    315       }
    316 
    317       for (Next = Index + 1; Next < UFS_MAX_LUNS; Next++) {
    318         if ((Private->Luns.BitMask & (BIT0 << Next)) != 0) {
    319           UfsLun = Private->Luns.Lun[Next];
    320           break;
    321         }
    322       }
    323 
    324       if (Next == UFS_MAX_LUNS) {
    325         return EFI_NOT_FOUND;
    326       } else {
    327         break;
    328       }
    329     }
    330 
    331     if (Index != UFS_MAX_LUNS) {
    332       *Lun = 0;
    333       if ((UfsLun & BIT7) == BIT7) {
    334         ((UINT8*)Lun)[0] = UFS_WLUN_PREFIX;
    335         ((UINT8*)Lun)[1] = UfsLun & ~BIT7;
    336       } else {
    337         ((UINT8*)Lun)[1] = UfsLun;
    338       }
    339       return EFI_SUCCESS;
    340     } else {
    341       return EFI_NOT_FOUND;
    342     }
    343   }
    344 
    345   return EFI_NOT_FOUND;
    346 }
    347 
    348 /**
    349   Used to allocate and build a device path node for a SCSI device on a SCSI channel.
    350 
    351   @param  This       A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
    352   @param  Target     The Target is an array of size TARGET_MAX_BYTES and it specifies the
    353                      Target ID of the SCSI device for which a device path node is to be
    354                      allocated and built. Transport drivers may chose to utilize a subset of
    355                      this size to suit the representation of targets. For example, a Fibre
    356                      Channel driver may use only 8 bytes (WWN) in the array to represent a
    357                      FC target.
    358   @param  Lun        The LUN of the SCSI device for which a device path node is to be
    359                      allocated and built.
    360   @param  DevicePath A pointer to a single device path node that describes the SCSI device
    361                      specified by Target and Lun. This function is responsible for
    362                      allocating the buffer DevicePath with the boot service
    363                      AllocatePool(). It is the caller's responsibility to free
    364                      DevicePath when the caller is finished with DevicePath.
    365 
    366   @retval EFI_SUCCESS           The device path node that describes the SCSI device specified by
    367                                 Target and Lun was allocated and returned in
    368                                 DevicePath.
    369   @retval EFI_INVALID_PARAMETER DevicePath is NULL.
    370   @retval EFI_NOT_FOUND         The SCSI devices specified by Target and Lun does not exist
    371                                 on the SCSI channel.
    372   @retval EFI_OUT_OF_RESOURCES  There are not enough resources to allocate DevicePath.
    373 
    374 **/
    375 EFI_STATUS
    376 EFIAPI
    377 UfsPassThruBuildDevicePath (
    378   IN     EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    379   IN     UINT8                              *Target,
    380   IN     UINT64                             Lun,
    381   IN OUT EFI_DEVICE_PATH_PROTOCOL           **DevicePath
    382   )
    383 {
    384   UFS_PASS_THRU_PRIVATE_DATA      *Private;
    385   EFI_DEV_PATH                    *DevicePathNode;
    386   UINT8                           UfsLun;
    387   UINT16                          Index;
    388 
    389   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
    390 
    391   //
    392   // Validate parameters passed in.
    393   //
    394   SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
    395   if (CompareMem (Target, mUfsTargetId, TARGET_MAX_BYTES) != 0) {
    396     return EFI_INVALID_PARAMETER;
    397   }
    398 
    399   if ((UINT8)Lun == UFS_WLUN_PREFIX) {
    400     UfsLun = BIT7 | (((UINT8*)&Lun)[1] & 0xFF);
    401   } else if ((UINT8)Lun == 0) {
    402     UfsLun = ((UINT8*)&Lun)[1] & 0xFF;
    403   } else {
    404     return EFI_NOT_FOUND;
    405   }
    406 
    407   for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
    408     if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
    409       continue;
    410     }
    411 
    412     if (Private->Luns.Lun[Index] == UfsLun) {
    413       break;
    414     }
    415   }
    416 
    417   if (Index == UFS_MAX_LUNS) {
    418     return EFI_NOT_FOUND;
    419   }
    420 
    421   DevicePathNode = AllocateCopyPool (sizeof (UFS_DEVICE_PATH), &mUfsDevicePathTemplate);
    422   if (DevicePathNode == NULL) {
    423     return EFI_OUT_OF_RESOURCES;
    424   }
    425 
    426   DevicePathNode->Ufs.Pun = 0;
    427   DevicePathNode->Ufs.Lun = UfsLun;
    428 
    429   *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DevicePathNode;
    430 
    431   return EFI_SUCCESS;
    432 }
    433 
    434 /**
    435   Used to translate a device path node to a Target ID and LUN.
    436 
    437   @param  This       A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
    438   @param  DevicePath A pointer to a single device path node that describes the SCSI device
    439                      on the SCSI channel.
    440   @param  Target     A pointer to the Target Array which represents the ID of a SCSI device
    441                      on the SCSI channel.
    442   @param  Lun        A pointer to the LUN of a SCSI device on the SCSI channel.
    443 
    444   @retval EFI_SUCCESS           DevicePath was successfully translated to a Target ID and
    445                                 LUN, and they were returned in Target and Lun.
    446   @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL.
    447   @retval EFI_NOT_FOUND         A valid translation from DevicePath to a Target ID and LUN
    448                                 does not exist.
    449   @retval EFI_UNSUPPORTED       This driver does not support the device path node type in
    450                                  DevicePath.
    451 
    452 **/
    453 EFI_STATUS
    454 EFIAPI
    455 UfsPassThruGetTargetLun (
    456   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    457   IN  EFI_DEVICE_PATH_PROTOCOL           *DevicePath,
    458   OUT UINT8                              **Target,
    459   OUT UINT64                             *Lun
    460   )
    461 {
    462   UFS_PASS_THRU_PRIVATE_DATA      *Private;
    463   EFI_DEV_PATH                    *DevicePathNode;
    464   UINT8                           Pun;
    465   UINT8                           UfsLun;
    466   UINT16                          Index;
    467 
    468   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
    469 
    470   //
    471   // Validate parameters passed in.
    472   //
    473   if (DevicePath == NULL || Target == NULL || Lun == NULL) {
    474     return EFI_INVALID_PARAMETER;
    475   }
    476 
    477   if (*Target == NULL) {
    478     return EFI_INVALID_PARAMETER;
    479   }
    480 
    481   //
    482   // Check whether the DevicePath belongs to SCSI_DEVICE_PATH
    483   //
    484   if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || (DevicePath->SubType != MSG_UFS_DP) ||
    485       (DevicePathNodeLength(DevicePath) != sizeof(SCSI_DEVICE_PATH))) {
    486     return EFI_UNSUPPORTED;
    487   }
    488 
    489   DevicePathNode = (EFI_DEV_PATH *) DevicePath;
    490 
    491   Pun    = (UINT8) DevicePathNode->Ufs.Pun;
    492   UfsLun = (UINT8) DevicePathNode->Ufs.Lun;
    493 
    494   if (Pun != 0) {
    495     return EFI_NOT_FOUND;
    496   }
    497 
    498   for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
    499     if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
    500       continue;
    501     }
    502 
    503     if (Private->Luns.Lun[Index] == UfsLun) {
    504       break;
    505     }
    506   }
    507 
    508   if (Index == UFS_MAX_LUNS) {
    509     return EFI_NOT_FOUND;
    510   }
    511 
    512   SetMem (*Target, TARGET_MAX_BYTES, 0x00);
    513   *Lun = 0;
    514   if ((UfsLun & BIT7) == BIT7) {
    515     ((UINT8*)Lun)[0] = UFS_WLUN_PREFIX;
    516     ((UINT8*)Lun)[1] = UfsLun & ~BIT7;
    517   } else {
    518     ((UINT8*)Lun)[1] = UfsLun;
    519   }
    520   return EFI_SUCCESS;
    521 }
    522 
    523 /**
    524   Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel.
    525 
    526   @param  This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
    527 
    528   @retval EFI_SUCCESS      The SCSI channel was reset.
    529   @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel.
    530   @retval EFI_TIMEOUT      A timeout occurred while attempting to reset the SCSI channel.
    531   @retval EFI_UNSUPPORTED  The SCSI channel does not support a channel reset operation.
    532 
    533 **/
    534 EFI_STATUS
    535 EFIAPI
    536 UfsPassThruResetChannel (
    537   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL   *This
    538   )
    539 {
    540   //
    541   // Return success directly then upper layer driver could think reset channel operation is done.
    542   //
    543   return EFI_SUCCESS;
    544 }
    545 
    546 /**
    547   Resets a SCSI logical unit that is connected to a SCSI channel.
    548 
    549   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
    550   @param  Target The Target is an array of size TARGET_MAX_BYTE and it represents the
    551                  target port ID of the SCSI device containing the SCSI logical unit to
    552                  reset. Transport drivers may chose to utilize a subset of this array to suit
    553                  the representation of their targets.
    554   @param  Lun    The LUN of the SCSI device to reset.
    555 
    556   @retval EFI_SUCCESS           The SCSI device specified by Target and Lun was reset.
    557   @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
    558   @retval EFI_TIMEOUT           A timeout occurred while attempting to reset the SCSI device
    559                                 specified by Target and Lun.
    560   @retval EFI_UNSUPPORTED       The SCSI channel does not support a target reset operation.
    561   @retval EFI_DEVICE_ERROR      A device error occurred while attempting to reset the SCSI device
    562                                  specified by Target and Lun.
    563 
    564 **/
    565 EFI_STATUS
    566 EFIAPI
    567 UfsPassThruResetTargetLun (
    568   IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    569   IN UINT8                              *Target,
    570   IN UINT64                             Lun
    571   )
    572 {
    573   //
    574   // Return success directly then upper layer driver could think reset target LUN operation is done.
    575   //
    576   return EFI_SUCCESS;
    577 }
    578 
    579 /**
    580   Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either
    581   be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs
    582   for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to
    583   see if a SCSI device is actually present at that location on the SCSI channel.
    584 
    585   @param  This   A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
    586   @param  Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
    587                  On output, a pointer to the Target ID (an array of
    588                  TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
    589                  channel. An input value of 0xF(all bytes in the array are 0xF) in the
    590                  Target array retrieves the Target ID of the first SCSI device present on a
    591                  SCSI channel.
    592 
    593   @retval EFI_SUCCESS           The Target ID of the next SCSI device on the SCSI
    594                                 channel was returned in Target.
    595   @retval EFI_INVALID_PARAMETER Target or Lun is NULL.
    596   @retval EFI_TIMEOUT           Target array is not all 0xF, and Target was not
    597                                 returned on a previous call to GetNextTarget().
    598   @retval EFI_NOT_FOUND         There are no more SCSI devices on this SCSI channel.
    599 
    600 **/
    601 EFI_STATUS
    602 EFIAPI
    603 UfsPassThruGetNextTarget (
    604   IN  EFI_EXT_SCSI_PASS_THRU_PROTOCOL    *This,
    605   IN OUT UINT8                           **Target
    606   )
    607 {
    608   UFS_PASS_THRU_PRIVATE_DATA      *Private;
    609 
    610   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
    611 
    612   if (Target == NULL || *Target == NULL) {
    613     return EFI_INVALID_PARAMETER;
    614   }
    615 
    616   SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0xFF);
    617   if (CompareMem(*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
    618     SetMem (*Target, TARGET_MAX_BYTES, 0x00);
    619     return EFI_SUCCESS;
    620   }
    621 
    622   return EFI_NOT_FOUND;
    623 }
    624 
    625 /**
    626   Tests to see if this driver supports a given controller. If a child device is provided,
    627   it further tests to see if this driver supports creating a handle for the specified child device.
    628 
    629   This function checks to see if the driver specified by This supports the device specified by
    630   ControllerHandle. Drivers will typically use the device path attached to
    631   ControllerHandle and/or the services from the bus I/O abstraction attached to
    632   ControllerHandle to determine if the driver supports ControllerHandle. This function
    633   may be called many times during platform initialization. In order to reduce boot times, the tests
    634   performed by this function must be very small, and take as little time as possible to execute. This
    635   function must not change the state of any hardware devices, and this function must be aware that the
    636   device specified by ControllerHandle may already be managed by the same driver or a
    637   different driver. This function must match its calls to AllocatePages() with FreePages(),
    638   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    639   Since ControllerHandle may have been previously started by the same driver, if a protocol is
    640   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    641   to guarantee the state of ControllerHandle is not modified by this function.
    642 
    643   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    644   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    645                                    must support a protocol interface that supplies
    646                                    an I/O abstraction to the driver.
    647   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    648                                    parameter is ignored by device drivers, and is optional for bus
    649                                    drivers. For bus drivers, if this parameter is not NULL, then
    650                                    the bus driver must determine if the bus controller specified
    651                                    by ControllerHandle and the child controller specified
    652                                    by RemainingDevicePath are both supported by this
    653                                    bus driver.
    654 
    655   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    656                                    RemainingDevicePath is supported by the driver specified by This.
    657   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    658                                    RemainingDevicePath is already being managed by the driver
    659                                    specified by This.
    660   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    661                                    RemainingDevicePath is already being managed by a different
    662                                    driver or an application that requires exclusive access.
    663                                    Currently not implemented.
    664   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    665                                    RemainingDevicePath is not supported by the driver specified by This.
    666 **/
    667 EFI_STATUS
    668 EFIAPI
    669 UfsPassThruDriverBindingSupported (
    670   IN EFI_DRIVER_BINDING_PROTOCOL       *This,
    671   IN EFI_HANDLE                        Controller,
    672   IN EFI_DEVICE_PATH_PROTOCOL          *RemainingDevicePath
    673   )
    674 {
    675   EFI_STATUS                           Status;
    676   EFI_DEVICE_PATH_PROTOCOL             *ParentDevicePath;
    677   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHostController;
    678 
    679   //
    680   // Ufs Pass Thru driver is a device driver, and should ingore the
    681   // "RemainingDevicePath" according to UEFI spec
    682   //
    683   Status = gBS->OpenProtocol (
    684                   Controller,
    685                   &gEfiDevicePathProtocolGuid,
    686                   (VOID *) &ParentDevicePath,
    687                   This->DriverBindingHandle,
    688                   Controller,
    689                   EFI_OPEN_PROTOCOL_BY_DRIVER
    690                   );
    691   if (EFI_ERROR (Status)) {
    692     //
    693     // EFI_ALREADY_STARTED is also an error
    694     //
    695     return Status;
    696   }
    697   //
    698   // Close the protocol because we don't use it here
    699   //
    700   gBS->CloseProtocol (
    701                   Controller,
    702                   &gEfiDevicePathProtocolGuid,
    703                   This->DriverBindingHandle,
    704                   Controller
    705                   );
    706 
    707   Status = gBS->OpenProtocol (
    708                   Controller,
    709                   &gEdkiiUfsHostControllerProtocolGuid,
    710                   (VOID **) &UfsHostController,
    711                   This->DriverBindingHandle,
    712                   Controller,
    713                   EFI_OPEN_PROTOCOL_BY_DRIVER
    714                   );
    715 
    716   if (EFI_ERROR (Status)) {
    717     //
    718     // EFI_ALREADY_STARTED is also an error
    719     //
    720     return Status;
    721   }
    722 
    723   //
    724   // Close the I/O Abstraction(s) used to perform the supported test
    725   //
    726   gBS->CloseProtocol (
    727         Controller,
    728         &gEdkiiUfsHostControllerProtocolGuid,
    729         This->DriverBindingHandle,
    730         Controller
    731         );
    732 
    733   return EFI_SUCCESS;
    734 }
    735 
    736 /**
    737   Starts a device controller or a bus controller.
    738 
    739   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    740   As a result, much of the error checking on the parameters to Start() has been moved into this
    741   common boot service. It is legal to call Start() from other locations,
    742   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    743   1. ControllerHandle must be a valid EFI_HANDLE.
    744   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    745      EFI_DEVICE_PATH_PROTOCOL.
    746   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    747      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    748 
    749   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    750   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    751                                    must support a protocol interface that supplies
    752                                    an I/O abstraction to the driver.
    753   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    754                                    parameter is ignored by device drivers, and is optional for bus
    755                                    drivers. For a bus driver, if this parameter is NULL, then handles
    756                                    for all the children of Controller are created by this driver.
    757                                    If this parameter is not NULL and the first Device Path Node is
    758                                    not the End of Device Path Node, then only the handle for the
    759                                    child device specified by the first Device Path Node of
    760                                    RemainingDevicePath is created by this driver.
    761                                    If the first Device Path Node of RemainingDevicePath is
    762                                    the End of Device Path Node, no child handle is created by this
    763                                    driver.
    764 
    765   @retval EFI_SUCCESS              The device was started.
    766   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    767   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    768   @retval Others                   The driver failded to start the device.
    769 
    770 **/
    771 EFI_STATUS
    772 EFIAPI
    773 UfsPassThruDriverBindingStart (
    774   IN EFI_DRIVER_BINDING_PROTOCOL        *This,
    775   IN EFI_HANDLE                         Controller,
    776   IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath
    777   )
    778 {
    779   EFI_STATUS                            Status;
    780   EDKII_UFS_HOST_CONTROLLER_PROTOCOL    *UfsHc;
    781   UFS_PASS_THRU_PRIVATE_DATA            *Private;
    782   UINTN                                 UfsHcBase;
    783   UINT32                                Index;
    784   UFS_CONFIG_DESC                       Config;
    785 
    786   Status    = EFI_SUCCESS;
    787   UfsHc     = NULL;
    788   Private   = NULL;
    789   UfsHcBase = 0;
    790 
    791   DEBUG ((EFI_D_INFO, "==UfsPassThru Start== Controller = %x\n", Controller));
    792 
    793   Status  = gBS->OpenProtocol (
    794                    Controller,
    795                    &gEdkiiUfsHostControllerProtocolGuid,
    796                    (VOID **) &UfsHc,
    797                    This->DriverBindingHandle,
    798                    Controller,
    799                    EFI_OPEN_PROTOCOL_BY_DRIVER
    800                    );
    801 
    802   if (EFI_ERROR (Status)) {
    803     DEBUG ((EFI_D_ERROR, "Open Ufs Host Controller Protocol Error, Status = %r\n", Status));
    804     goto Error;
    805   }
    806 
    807   //
    808   // Get the UFS Host Controller MMIO Bar Base Address.
    809   //
    810   Status = UfsHc->GetUfsHcMmioBar (UfsHc, &UfsHcBase);
    811   if (EFI_ERROR (Status)) {
    812     DEBUG ((EFI_D_ERROR, "Get Ufs Host Controller Mmio Bar Error, Status = %r\n", Status));
    813     goto Error;
    814   }
    815 
    816   //
    817   // Initialize Ufs Pass Thru private data for managed UFS Host Controller.
    818   //
    819   Private = AllocateCopyPool (sizeof (UFS_PASS_THRU_PRIVATE_DATA), &gUfsPassThruTemplate);
    820   if (Private == NULL) {
    821     DEBUG ((EFI_D_ERROR, "Unable to allocate Ufs Pass Thru private data\n"));
    822     Status = EFI_OUT_OF_RESOURCES;
    823     goto Error;
    824   }
    825 
    826   Private->ExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
    827   Private->UfsHostController    = UfsHc;
    828   Private->UfsHcBase            = UfsHcBase;
    829   InitializeListHead (&Private->Queue);
    830 
    831   //
    832   // Initialize UFS Host Controller H/W.
    833   //
    834   Status = UfsControllerInit (Private);
    835   if (EFI_ERROR (Status)) {
    836     DEBUG ((EFI_D_ERROR, "Ufs Host Controller Initialization Error, Status = %r\n", Status));
    837     goto Error;
    838   }
    839 
    840   //
    841   // UFS 2.0 spec Section 13.1.3.3:
    842   // At the end of the UFS Interconnect Layer initialization on both host and device side,
    843   // the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.
    844   //
    845   Status = UfsExecNopCmds (Private);
    846   if (EFI_ERROR (Status)) {
    847     DEBUG ((EFI_D_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));
    848     goto Error;
    849   }
    850 
    851   //
    852   // The host enables the device initialization completion by setting fDeviceInit flag.
    853   //
    854   Status = UfsSetFlag (Private, UfsFlagDevInit);
    855   if (EFI_ERROR (Status)) {
    856     DEBUG ((EFI_D_ERROR, "Ufs Set fDeviceInit Flag Error, Status = %r\n", Status));
    857     goto Error;
    858   }
    859 
    860   //
    861   // Get Ufs Device's Lun Info by reading Configuration Descriptor.
    862   //
    863   Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &Config, sizeof (UFS_CONFIG_DESC));
    864   if (EFI_ERROR (Status)) {
    865     DEBUG ((EFI_D_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));
    866     goto Error;
    867   }
    868 
    869   //
    870   // Check if 8 common luns are active and set corresponding bit mask.
    871   // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper layer for authentication access.
    872   //
    873   for (Index = 0; Index < 8; Index++) {
    874     if (Config.UnitDescConfParams[Index].LunEn != 0) {
    875       Private->Luns.BitMask |= (BIT0 << Index);
    876       DEBUG ((EFI_D_INFO, "Ufs Lun %d is enabled\n", Index));
    877     }
    878   }
    879 
    880   //
    881   // Start the asynchronous interrupt monitor
    882   //
    883   Status = gBS->CreateEvent (
    884                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
    885                   TPL_NOTIFY,
    886                   ProcessAsyncTaskList,
    887                   Private,
    888                   &Private->TimerEvent
    889                   );
    890   if (EFI_ERROR (Status)) {
    891     DEBUG ((EFI_D_ERROR, "Ufs Create Async Tasks Event Error, Status = %r\n", Status));
    892     goto Error;
    893   }
    894 
    895   Status = gBS->SetTimer (
    896                   Private->TimerEvent,
    897                   TimerPeriodic,
    898                   UFS_HC_ASYNC_TIMER
    899                   );
    900   if (EFI_ERROR (Status)) {
    901     DEBUG ((EFI_D_ERROR, "Ufs Set Periodic Timer Error, Status = %r\n", Status));
    902     goto Error;
    903   }
    904 
    905   Status = gBS->InstallProtocolInterface (
    906                   &Controller,
    907                   &gEfiExtScsiPassThruProtocolGuid,
    908                   EFI_NATIVE_INTERFACE,
    909                   &(Private->ExtScsiPassThru)
    910                   );
    911   ASSERT_EFI_ERROR (Status);
    912 
    913   return EFI_SUCCESS;
    914 
    915 Error:
    916   if (Private != NULL) {
    917     if (Private->TmrlMapping != NULL) {
    918       UfsHc->Unmap (UfsHc, Private->TmrlMapping);
    919     }
    920     if (Private->UtpTmrlBase != NULL) {
    921       UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
    922     }
    923 
    924     if (Private->TrlMapping != NULL) {
    925       UfsHc->Unmap (UfsHc, Private->TrlMapping);
    926     }
    927     if (Private->UtpTrlBase != NULL) {
    928       UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
    929     }
    930 
    931     if (Private->TimerEvent != NULL) {
    932       gBS->CloseEvent (Private->TimerEvent);
    933     }
    934 
    935     FreePool (Private);
    936   }
    937 
    938   if (UfsHc != NULL) {
    939     gBS->CloseProtocol (
    940            Controller,
    941            &gEdkiiUfsHostControllerProtocolGuid,
    942            This->DriverBindingHandle,
    943            Controller
    944            );
    945   }
    946 
    947   return Status;
    948 }
    949 
    950 /**
    951   Stops a device controller or a bus controller.
    952 
    953   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    954   As a result, much of the error checking on the parameters to Stop() has been moved
    955   into this common boot service. It is legal to call Stop() from other locations,
    956   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    957   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    958      same driver's Start() function.
    959   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    960      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    961      Start() function, and the Start() function must have called OpenProtocol() on
    962      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    963 
    964   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    965   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    966                                 support a bus specific I/O protocol for the driver
    967                                 to use to stop the device.
    968   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    969   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    970                                 if NumberOfChildren is 0.
    971 
    972   @retval EFI_SUCCESS           The device was stopped.
    973   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    974 
    975 **/
    976 EFI_STATUS
    977 EFIAPI
    978 UfsPassThruDriverBindingStop (
    979   IN  EFI_DRIVER_BINDING_PROTOCOL       *This,
    980   IN  EFI_HANDLE                        Controller,
    981   IN  UINTN                             NumberOfChildren,
    982   IN  EFI_HANDLE                        *ChildHandleBuffer
    983   )
    984 {
    985   EFI_STATUS                            Status;
    986   UFS_PASS_THRU_PRIVATE_DATA            *Private;
    987   EFI_EXT_SCSI_PASS_THRU_PROTOCOL       *ExtScsiPassThru;
    988   EDKII_UFS_HOST_CONTROLLER_PROTOCOL    *UfsHc;
    989   UFS_PASS_THRU_TRANS_REQ               *TransReq;
    990   LIST_ENTRY                            *Entry;
    991   LIST_ENTRY                            *NextEntry;
    992 
    993   DEBUG ((EFI_D_INFO, "==UfsPassThru Stop== Controller Controller = %x\n", Controller));
    994 
    995   Status = gBS->OpenProtocol (
    996                   Controller,
    997                   &gEfiExtScsiPassThruProtocolGuid,
    998                   (VOID **) &ExtScsiPassThru,
    999                   This->DriverBindingHandle,
   1000                   Controller,
   1001                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1002                   );
   1003 
   1004   if (EFI_ERROR (Status)) {
   1005     return EFI_DEVICE_ERROR;
   1006   }
   1007 
   1008   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (ExtScsiPassThru);
   1009   UfsHc   = Private->UfsHostController;
   1010 
   1011   //
   1012   // Cleanup the resources of I/O requests in the async I/O queue
   1013   //
   1014   if (!IsListEmpty(&Private->Queue)) {
   1015     EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
   1016       TransReq  = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
   1017 
   1018       //
   1019       // TODO: Should find/add a proper host adapter return status for this
   1020       // case.
   1021       //
   1022       TransReq->Packet->HostAdapterStatus =
   1023         EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
   1024 
   1025       SignalCallerEvent (Private, TransReq);
   1026     }
   1027   }
   1028 
   1029   Status = gBS->UninstallProtocolInterface (
   1030                   Controller,
   1031                   &gEfiExtScsiPassThruProtocolGuid,
   1032                   &(Private->ExtScsiPassThru)
   1033                   );
   1034 
   1035   if (EFI_ERROR (Status)) {
   1036     return EFI_DEVICE_ERROR;
   1037   }
   1038 
   1039   //
   1040   // Stop Ufs Host Controller
   1041   //
   1042   Status = UfsControllerStop (Private);
   1043   ASSERT_EFI_ERROR (Status);
   1044 
   1045   if (Private->TmrlMapping != NULL) {
   1046     UfsHc->Unmap (UfsHc, Private->TmrlMapping);
   1047   }
   1048   if (Private->UtpTmrlBase != NULL) {
   1049     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
   1050   }
   1051 
   1052   if (Private->TrlMapping != NULL) {
   1053     UfsHc->Unmap (UfsHc, Private->TrlMapping);
   1054   }
   1055   if (Private->UtpTrlBase != NULL) {
   1056     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
   1057   }
   1058 
   1059   if (Private->TimerEvent != NULL) {
   1060     gBS->CloseEvent (Private->TimerEvent);
   1061   }
   1062 
   1063   FreePool (Private);
   1064 
   1065   //
   1066   // Close protocols opened by UfsPassThru controller driver
   1067   //
   1068   gBS->CloseProtocol (
   1069          Controller,
   1070          &gEdkiiUfsHostControllerProtocolGuid,
   1071          This->DriverBindingHandle,
   1072          Controller
   1073          );
   1074 
   1075   return Status;
   1076 }
   1077 
   1078 
   1079 /**
   1080   The user Entry Point for module UfsPassThru. The user code starts with this function.
   1081 
   1082   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1083   @param[in] SystemTable    A pointer to the EFI System Table.
   1084 
   1085   @retval EFI_SUCCESS       The entry point is executed successfully.
   1086   @retval other             Some error occurs when executing this entry point.
   1087 
   1088 **/
   1089 EFI_STATUS
   1090 EFIAPI
   1091 InitializeUfsPassThru (
   1092   IN EFI_HANDLE           ImageHandle,
   1093   IN EFI_SYSTEM_TABLE     *SystemTable
   1094   )
   1095 {
   1096   EFI_STATUS              Status;
   1097 
   1098   //
   1099   // Install driver model protocol(s).
   1100   //
   1101   Status = EfiLibInstallDriverBindingComponentName2 (
   1102              ImageHandle,
   1103              SystemTable,
   1104              &gUfsPassThruDriverBinding,
   1105              ImageHandle,
   1106              &gUfsPassThruComponentName,
   1107              &gUfsPassThruComponentName2
   1108              );
   1109   ASSERT_EFI_ERROR (Status);
   1110 
   1111   return Status;
   1112 }
   1113