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   if (Target == NULL || *Target == NULL) {
    609     return EFI_INVALID_PARAMETER;
    610   }
    611 
    612   SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0xFF);
    613   if (CompareMem(*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
    614     SetMem (*Target, TARGET_MAX_BYTES, 0x00);
    615     return EFI_SUCCESS;
    616   }
    617 
    618   return EFI_NOT_FOUND;
    619 }
    620 
    621 /**
    622   Tests to see if this driver supports a given controller. If a child device is provided,
    623   it further tests to see if this driver supports creating a handle for the specified child device.
    624 
    625   This function checks to see if the driver specified by This supports the device specified by
    626   ControllerHandle. Drivers will typically use the device path attached to
    627   ControllerHandle and/or the services from the bus I/O abstraction attached to
    628   ControllerHandle to determine if the driver supports ControllerHandle. This function
    629   may be called many times during platform initialization. In order to reduce boot times, the tests
    630   performed by this function must be very small, and take as little time as possible to execute. This
    631   function must not change the state of any hardware devices, and this function must be aware that the
    632   device specified by ControllerHandle may already be managed by the same driver or a
    633   different driver. This function must match its calls to AllocatePages() with FreePages(),
    634   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    635   Since ControllerHandle may have been previously started by the same driver, if a protocol is
    636   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    637   to guarantee the state of ControllerHandle is not modified by this function.
    638 
    639   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    640   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    641                                    must support a protocol interface that supplies
    642                                    an I/O abstraction to the driver.
    643   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    644                                    parameter is ignored by device drivers, and is optional for bus
    645                                    drivers. For bus drivers, if this parameter is not NULL, then
    646                                    the bus driver must determine if the bus controller specified
    647                                    by ControllerHandle and the child controller specified
    648                                    by RemainingDevicePath are both supported by this
    649                                    bus driver.
    650 
    651   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    652                                    RemainingDevicePath is supported by the driver specified by This.
    653   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    654                                    RemainingDevicePath is already being managed by the driver
    655                                    specified by This.
    656   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    657                                    RemainingDevicePath is already being managed by a different
    658                                    driver or an application that requires exclusive access.
    659                                    Currently not implemented.
    660   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    661                                    RemainingDevicePath is not supported by the driver specified by This.
    662 **/
    663 EFI_STATUS
    664 EFIAPI
    665 UfsPassThruDriverBindingSupported (
    666   IN EFI_DRIVER_BINDING_PROTOCOL       *This,
    667   IN EFI_HANDLE                        Controller,
    668   IN EFI_DEVICE_PATH_PROTOCOL          *RemainingDevicePath
    669   )
    670 {
    671   EFI_STATUS                           Status;
    672   EFI_DEVICE_PATH_PROTOCOL             *ParentDevicePath;
    673   EDKII_UFS_HOST_CONTROLLER_PROTOCOL   *UfsHostController;
    674 
    675   //
    676   // Ufs Pass Thru driver is a device driver, and should ingore the
    677   // "RemainingDevicePath" according to UEFI spec
    678   //
    679   Status = gBS->OpenProtocol (
    680                   Controller,
    681                   &gEfiDevicePathProtocolGuid,
    682                   (VOID *) &ParentDevicePath,
    683                   This->DriverBindingHandle,
    684                   Controller,
    685                   EFI_OPEN_PROTOCOL_BY_DRIVER
    686                   );
    687   if (EFI_ERROR (Status)) {
    688     //
    689     // EFI_ALREADY_STARTED is also an error
    690     //
    691     return Status;
    692   }
    693   //
    694   // Close the protocol because we don't use it here
    695   //
    696   gBS->CloseProtocol (
    697                   Controller,
    698                   &gEfiDevicePathProtocolGuid,
    699                   This->DriverBindingHandle,
    700                   Controller
    701                   );
    702 
    703   Status = gBS->OpenProtocol (
    704                   Controller,
    705                   &gEdkiiUfsHostControllerProtocolGuid,
    706                   (VOID **) &UfsHostController,
    707                   This->DriverBindingHandle,
    708                   Controller,
    709                   EFI_OPEN_PROTOCOL_BY_DRIVER
    710                   );
    711 
    712   if (EFI_ERROR (Status)) {
    713     //
    714     // EFI_ALREADY_STARTED is also an error
    715     //
    716     return Status;
    717   }
    718 
    719   //
    720   // Close the I/O Abstraction(s) used to perform the supported test
    721   //
    722   gBS->CloseProtocol (
    723         Controller,
    724         &gEdkiiUfsHostControllerProtocolGuid,
    725         This->DriverBindingHandle,
    726         Controller
    727         );
    728 
    729   return EFI_SUCCESS;
    730 }
    731 
    732 /**
    733   Starts a device controller or a bus controller.
    734 
    735   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    736   As a result, much of the error checking on the parameters to Start() has been moved into this
    737   common boot service. It is legal to call Start() from other locations,
    738   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    739   1. ControllerHandle must be a valid EFI_HANDLE.
    740   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    741      EFI_DEVICE_PATH_PROTOCOL.
    742   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    743      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    744 
    745   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    746   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    747                                    must support a protocol interface that supplies
    748                                    an I/O abstraction to the driver.
    749   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    750                                    parameter is ignored by device drivers, and is optional for bus
    751                                    drivers. For a bus driver, if this parameter is NULL, then handles
    752                                    for all the children of Controller are created by this driver.
    753                                    If this parameter is not NULL and the first Device Path Node is
    754                                    not the End of Device Path Node, then only the handle for the
    755                                    child device specified by the first Device Path Node of
    756                                    RemainingDevicePath is created by this driver.
    757                                    If the first Device Path Node of RemainingDevicePath is
    758                                    the End of Device Path Node, no child handle is created by this
    759                                    driver.
    760 
    761   @retval EFI_SUCCESS              The device was started.
    762   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    763   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    764   @retval Others                   The driver failded to start the device.
    765 
    766 **/
    767 EFI_STATUS
    768 EFIAPI
    769 UfsPassThruDriverBindingStart (
    770   IN EFI_DRIVER_BINDING_PROTOCOL        *This,
    771   IN EFI_HANDLE                         Controller,
    772   IN EFI_DEVICE_PATH_PROTOCOL           *RemainingDevicePath
    773   )
    774 {
    775   EFI_STATUS                            Status;
    776   EDKII_UFS_HOST_CONTROLLER_PROTOCOL    *UfsHc;
    777   UFS_PASS_THRU_PRIVATE_DATA            *Private;
    778   UINTN                                 UfsHcBase;
    779   UINT32                                Index;
    780   UFS_CONFIG_DESC                       Config;
    781 
    782   Status    = EFI_SUCCESS;
    783   UfsHc     = NULL;
    784   Private   = NULL;
    785   UfsHcBase = 0;
    786 
    787   DEBUG ((EFI_D_INFO, "==UfsPassThru Start== Controller = %x\n", Controller));
    788 
    789   Status  = gBS->OpenProtocol (
    790                    Controller,
    791                    &gEdkiiUfsHostControllerProtocolGuid,
    792                    (VOID **) &UfsHc,
    793                    This->DriverBindingHandle,
    794                    Controller,
    795                    EFI_OPEN_PROTOCOL_BY_DRIVER
    796                    );
    797 
    798   if (EFI_ERROR (Status)) {
    799     DEBUG ((EFI_D_ERROR, "Open Ufs Host Controller Protocol Error, Status = %r\n", Status));
    800     goto Error;
    801   }
    802 
    803   //
    804   // Get the UFS Host Controller MMIO Bar Base Address.
    805   //
    806   Status = UfsHc->GetUfsHcMmioBar (UfsHc, &UfsHcBase);
    807   if (EFI_ERROR (Status)) {
    808     DEBUG ((EFI_D_ERROR, "Get Ufs Host Controller Mmio Bar Error, Status = %r\n", Status));
    809     goto Error;
    810   }
    811 
    812   //
    813   // Initialize Ufs Pass Thru private data for managed UFS Host Controller.
    814   //
    815   Private = AllocateCopyPool (sizeof (UFS_PASS_THRU_PRIVATE_DATA), &gUfsPassThruTemplate);
    816   if (Private == NULL) {
    817     DEBUG ((EFI_D_ERROR, "Unable to allocate Ufs Pass Thru private data\n"));
    818     Status = EFI_OUT_OF_RESOURCES;
    819     goto Error;
    820   }
    821 
    822   Private->ExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
    823   Private->UfsHostController    = UfsHc;
    824   Private->UfsHcBase            = UfsHcBase;
    825   InitializeListHead (&Private->Queue);
    826 
    827   //
    828   // Initialize UFS Host Controller H/W.
    829   //
    830   Status = UfsControllerInit (Private);
    831   if (EFI_ERROR (Status)) {
    832     DEBUG ((EFI_D_ERROR, "Ufs Host Controller Initialization Error, Status = %r\n", Status));
    833     goto Error;
    834   }
    835 
    836   //
    837   // UFS 2.0 spec Section 13.1.3.3:
    838   // At the end of the UFS Interconnect Layer initialization on both host and device side,
    839   // the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.
    840   //
    841   Status = UfsExecNopCmds (Private);
    842   if (EFI_ERROR (Status)) {
    843     DEBUG ((EFI_D_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));
    844     goto Error;
    845   }
    846 
    847   //
    848   // The host enables the device initialization completion by setting fDeviceInit flag.
    849   //
    850   Status = UfsSetFlag (Private, UfsFlagDevInit);
    851   if (EFI_ERROR (Status)) {
    852     DEBUG ((EFI_D_ERROR, "Ufs Set fDeviceInit Flag Error, Status = %r\n", Status));
    853     goto Error;
    854   }
    855 
    856   MicroSecondDelay (100000);
    857 
    858   //
    859   // Get Ufs Device's Lun Info by reading Configuration Descriptor.
    860   //
    861   Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &Config, sizeof (UFS_CONFIG_DESC));
    862   if (EFI_ERROR (Status)) {
    863     DEBUG ((EFI_D_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));
    864     goto Error;
    865   }
    866 
    867   //
    868   // Check if 8 common luns are active and set corresponding bit mask.
    869   // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper layer for authentication access.
    870   //
    871   for (Index = 0; Index < 8; Index++) {
    872     if (Config.UnitDescConfParams[Index].LunEn != 0) {
    873       Private->Luns.BitMask |= (BIT0 << Index);
    874       DEBUG ((EFI_D_INFO, "Ufs Lun %d is enabled\n", Index));
    875     }
    876   }
    877 
    878   //
    879   // Start the asynchronous interrupt monitor
    880   //
    881   Status = gBS->CreateEvent (
    882                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
    883                   TPL_NOTIFY,
    884                   ProcessAsyncTaskList,
    885                   Private,
    886                   &Private->TimerEvent
    887                   );
    888   if (EFI_ERROR (Status)) {
    889     DEBUG ((EFI_D_ERROR, "Ufs Create Async Tasks Event Error, Status = %r\n", Status));
    890     goto Error;
    891   }
    892 
    893   Status = gBS->SetTimer (
    894                   Private->TimerEvent,
    895                   TimerPeriodic,
    896                   UFS_HC_ASYNC_TIMER
    897                   );
    898   if (EFI_ERROR (Status)) {
    899     DEBUG ((EFI_D_ERROR, "Ufs Set Periodic Timer Error, Status = %r\n", Status));
    900     goto Error;
    901   }
    902 
    903   Status = gBS->InstallProtocolInterface (
    904                   &Controller,
    905                   &gEfiExtScsiPassThruProtocolGuid,
    906                   EFI_NATIVE_INTERFACE,
    907                   &(Private->ExtScsiPassThru)
    908                   );
    909   ASSERT_EFI_ERROR (Status);
    910 
    911   return EFI_SUCCESS;
    912 
    913 Error:
    914   if (Private != NULL) {
    915     if (Private->TmrlMapping != NULL) {
    916       UfsHc->Unmap (UfsHc, Private->TmrlMapping);
    917     }
    918     if (Private->UtpTmrlBase != NULL) {
    919       UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
    920     }
    921 
    922     if (Private->TrlMapping != NULL) {
    923       UfsHc->Unmap (UfsHc, Private->TrlMapping);
    924     }
    925     if (Private->UtpTrlBase != NULL) {
    926       UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
    927     }
    928 
    929     if (Private->TimerEvent != NULL) {
    930       gBS->CloseEvent (Private->TimerEvent);
    931     }
    932 
    933     FreePool (Private);
    934   }
    935 
    936   if (UfsHc != NULL) {
    937     gBS->CloseProtocol (
    938            Controller,
    939            &gEdkiiUfsHostControllerProtocolGuid,
    940            This->DriverBindingHandle,
    941            Controller
    942            );
    943   }
    944 
    945   return Status;
    946 }
    947 
    948 /**
    949   Stops a device controller or a bus controller.
    950 
    951   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    952   As a result, much of the error checking on the parameters to Stop() has been moved
    953   into this common boot service. It is legal to call Stop() from other locations,
    954   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    955   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    956      same driver's Start() function.
    957   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    958      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    959      Start() function, and the Start() function must have called OpenProtocol() on
    960      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    961 
    962   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    963   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    964                                 support a bus specific I/O protocol for the driver
    965                                 to use to stop the device.
    966   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    967   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    968                                 if NumberOfChildren is 0.
    969 
    970   @retval EFI_SUCCESS           The device was stopped.
    971   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    972 
    973 **/
    974 EFI_STATUS
    975 EFIAPI
    976 UfsPassThruDriverBindingStop (
    977   IN  EFI_DRIVER_BINDING_PROTOCOL       *This,
    978   IN  EFI_HANDLE                        Controller,
    979   IN  UINTN                             NumberOfChildren,
    980   IN  EFI_HANDLE                        *ChildHandleBuffer
    981   )
    982 {
    983   EFI_STATUS                            Status;
    984   UFS_PASS_THRU_PRIVATE_DATA            *Private;
    985   EFI_EXT_SCSI_PASS_THRU_PROTOCOL       *ExtScsiPassThru;
    986   EDKII_UFS_HOST_CONTROLLER_PROTOCOL    *UfsHc;
    987   UFS_PASS_THRU_TRANS_REQ               *TransReq;
    988   LIST_ENTRY                            *Entry;
    989   LIST_ENTRY                            *NextEntry;
    990 
    991   DEBUG ((EFI_D_INFO, "==UfsPassThru Stop== Controller Controller = %x\n", Controller));
    992 
    993   Status = gBS->OpenProtocol (
    994                   Controller,
    995                   &gEfiExtScsiPassThruProtocolGuid,
    996                   (VOID **) &ExtScsiPassThru,
    997                   This->DriverBindingHandle,
    998                   Controller,
    999                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1000                   );
   1001 
   1002   if (EFI_ERROR (Status)) {
   1003     return EFI_DEVICE_ERROR;
   1004   }
   1005 
   1006   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (ExtScsiPassThru);
   1007   UfsHc   = Private->UfsHostController;
   1008 
   1009   //
   1010   // Cleanup the resources of I/O requests in the async I/O queue
   1011   //
   1012   if (!IsListEmpty(&Private->Queue)) {
   1013     EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
   1014       TransReq  = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
   1015 
   1016       //
   1017       // TODO: Should find/add a proper host adapter return status for this
   1018       // case.
   1019       //
   1020       TransReq->Packet->HostAdapterStatus =
   1021         EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
   1022 
   1023       SignalCallerEvent (Private, TransReq);
   1024     }
   1025   }
   1026 
   1027   Status = gBS->UninstallProtocolInterface (
   1028                   Controller,
   1029                   &gEfiExtScsiPassThruProtocolGuid,
   1030                   &(Private->ExtScsiPassThru)
   1031                   );
   1032 
   1033   if (EFI_ERROR (Status)) {
   1034     return EFI_DEVICE_ERROR;
   1035   }
   1036 
   1037   //
   1038   // Stop Ufs Host Controller
   1039   //
   1040   Status = UfsControllerStop (Private);
   1041   ASSERT_EFI_ERROR (Status);
   1042 
   1043   if (Private->TmrlMapping != NULL) {
   1044     UfsHc->Unmap (UfsHc, Private->TmrlMapping);
   1045   }
   1046   if (Private->UtpTmrlBase != NULL) {
   1047     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
   1048   }
   1049 
   1050   if (Private->TrlMapping != NULL) {
   1051     UfsHc->Unmap (UfsHc, Private->TrlMapping);
   1052   }
   1053   if (Private->UtpTrlBase != NULL) {
   1054     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
   1055   }
   1056 
   1057   if (Private->TimerEvent != NULL) {
   1058     gBS->CloseEvent (Private->TimerEvent);
   1059   }
   1060 
   1061   FreePool (Private);
   1062 
   1063   //
   1064   // Close protocols opened by UfsPassThru controller driver
   1065   //
   1066   gBS->CloseProtocol (
   1067          Controller,
   1068          &gEdkiiUfsHostControllerProtocolGuid,
   1069          This->DriverBindingHandle,
   1070          Controller
   1071          );
   1072 
   1073   return Status;
   1074 }
   1075 
   1076 
   1077 /**
   1078   The user Entry Point for module UfsPassThru. The user code starts with this function.
   1079 
   1080   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1081   @param[in] SystemTable    A pointer to the EFI System Table.
   1082 
   1083   @retval EFI_SUCCESS       The entry point is executed successfully.
   1084   @retval other             Some error occurs when executing this entry point.
   1085 
   1086 **/
   1087 EFI_STATUS
   1088 EFIAPI
   1089 InitializeUfsPassThru (
   1090   IN EFI_HANDLE           ImageHandle,
   1091   IN EFI_SYSTEM_TABLE     *SystemTable
   1092   )
   1093 {
   1094   EFI_STATUS              Status;
   1095 
   1096   //
   1097   // Install driver model protocol(s).
   1098   //
   1099   Status = EfiLibInstallDriverBindingComponentName2 (
   1100              ImageHandle,
   1101              SystemTable,
   1102              &gUfsPassThruDriverBinding,
   1103              ImageHandle,
   1104              &gUfsPassThruComponentName,
   1105              &gUfsPassThruComponentName2
   1106              );
   1107   ASSERT_EFI_ERROR (Status);
   1108 
   1109   return Status;
   1110 }
   1111