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
UfsPassThruPassThru(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN UINT8 * Target,IN UINT64 Lun,IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET * Packet,IN EFI_EVENT Event OPTIONAL)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
UfsPassThruGetNextTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN OUT UINT8 ** Target,IN OUT UINT64 * Lun)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
UfsPassThruBuildDevicePath(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN UINT8 * Target,IN UINT64 Lun,IN OUT EFI_DEVICE_PATH_PROTOCOL ** DevicePath)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
UfsPassThruGetTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN EFI_DEVICE_PATH_PROTOCOL * DevicePath,OUT UINT8 ** Target,OUT UINT64 * Lun)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
UfsPassThruResetChannel(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This)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
UfsPassThruResetTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN UINT8 * Target,IN UINT64 Lun)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
UfsPassThruGetNextTarget(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL * This,IN OUT UINT8 ** Target)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
UfsPassThruDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
UfsPassThruDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
UfsPassThruDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
InitializeUfsPassThru(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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