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   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
UfsPassThruDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
UfsPassThruDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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   UFS_DEV_DESC                          Dev;
782   UINT32                                DevQuirks;
783 
784   Status    = EFI_SUCCESS;
785   UfsHc     = NULL;
786   Private   = NULL;
787   UfsHcBase = 0;
788   DevQuirks = 0;
789 
790   DEBUG ((EFI_D_INFO, "==UfsPassThru Start== Controller = %x\n", Controller));
791 
792   Status  = gBS->OpenProtocol (
793                    Controller,
794                    &gEdkiiUfsHostControllerProtocolGuid,
795                    (VOID **) &UfsHc,
796                    This->DriverBindingHandle,
797                    Controller,
798                    EFI_OPEN_PROTOCOL_BY_DRIVER
799                    );
800 
801   if (EFI_ERROR (Status)) {
802     DEBUG ((EFI_D_ERROR, "Open Ufs Host Controller Protocol Error, Status = %r\n", Status));
803     goto Error;
804   }
805 
806   //
807   // Get the UFS Host Controller MMIO Bar Base Address.
808   //
809   Status = UfsHc->GetUfsHcMmioBar (UfsHc, &UfsHcBase);
810   if (EFI_ERROR (Status)) {
811     DEBUG ((EFI_D_ERROR, "Get Ufs Host Controller Mmio Bar Error, Status = %r\n", Status));
812     goto Error;
813   }
814 
815   //
816   // Initialize Ufs Pass Thru private data for managed UFS Host Controller.
817   //
818   Private = AllocateCopyPool (sizeof (UFS_PASS_THRU_PRIVATE_DATA), &gUfsPassThruTemplate);
819   if (Private == NULL) {
820     DEBUG ((EFI_D_ERROR, "Unable to allocate Ufs Pass Thru private data\n"));
821     Status = EFI_OUT_OF_RESOURCES;
822     goto Error;
823   }
824 
825   Private->ExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
826   Private->UfsHostController    = UfsHc;
827   Private->UfsHcBase            = UfsHcBase;
828   InitializeListHead (&Private->Queue);
829 
830   //
831   // Initialize UFS Host Controller H/W.
832   //
833   Status = UfsControllerInit (Private);
834   if (EFI_ERROR (Status)) {
835     DEBUG ((EFI_D_ERROR, "Ufs Host Controller Initialization Error, Status = %r\n", Status));
836     goto Error;
837   }
838 
839   //
840   // UFS 2.0 spec Section 13.1.3.3:
841   // At the end of the UFS Interconnect Layer initialization on both host and device side,
842   // the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.
843   //
844   Status = UfsExecNopCmds (Private);
845   if (EFI_ERROR (Status)) {
846     DEBUG ((EFI_D_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));
847     goto Error;
848   }
849 
850   //
851   // The host enables the device initialization completion by setting fDeviceInit flag.
852   //
853   Status = UfsSetFlag (Private, UfsFlagDevInit);
854   if (EFI_ERROR (Status)) {
855     DEBUG ((EFI_D_ERROR, "Ufs Set fDeviceInit Flag Error, Status = %r\n", Status));
856     goto Error;
857   }
858 
859   MicroSecondDelay (100000);
860 
861   Status = UfsRwDeviceDesc (Private, TRUE, UfsDeviceDesc, 0, 0, &Dev, sizeof (UFS_DEV_DESC));
862   if (EFI_ERROR (Status)) {
863     DEBUG ((EFI_D_ERROR, "Ufs Get Dev Descriptor Error, Status = %r\n", Status));
864     goto Error;
865   }
866 
867   if (SwapBytes16(Dev.ManufacturerId) == UFS_VENDOR_SKHYNIX) {
868     DevQuirks |= UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME;
869   }
870 
871   Status = UfsHc->PhySetPowerMode (UfsHc, DevQuirks);
872   if (EFI_ERROR (Status)) {
873     DEBUG ((EFI_D_ERROR, "Phy Set Power Mode Fails, Status = %r\n", Status));
874     goto Error;
875   }
876 
877   //
878   // Get Ufs Device's Lun Info by reading Configuration Descriptor.
879   //
880   Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &Config, sizeof (UFS_CONFIG_DESC));
881   if (EFI_ERROR (Status)) {
882     DEBUG ((EFI_D_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));
883     goto Error;
884   }
885 
886   //
887   // Check if 8 common luns are active and set corresponding bit mask.
888   // TODO: Parse device descriptor to decide if exposing RPMB LUN to upper layer for authentication access.
889   //
890   for (Index = 0; Index < 8; Index++) {
891     if (Config.UnitDescConfParams[Index].LunEn != 0) {
892       Private->Luns.BitMask |= (BIT0 << Index);
893       DEBUG ((EFI_D_INFO, "Ufs Lun %d is enabled\n", Index));
894     }
895   }
896 
897   //
898   // Start the asynchronous interrupt monitor
899   //
900   Status = gBS->CreateEvent (
901                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
902                   TPL_NOTIFY,
903                   ProcessAsyncTaskList,
904                   Private,
905                   &Private->TimerEvent
906                   );
907   if (EFI_ERROR (Status)) {
908     DEBUG ((EFI_D_ERROR, "Ufs Create Async Tasks Event Error, Status = %r\n", Status));
909     goto Error;
910   }
911 
912   Status = gBS->SetTimer (
913                   Private->TimerEvent,
914                   TimerPeriodic,
915                   UFS_HC_ASYNC_TIMER
916                   );
917   if (EFI_ERROR (Status)) {
918     DEBUG ((EFI_D_ERROR, "Ufs Set Periodic Timer Error, Status = %r\n", Status));
919     goto Error;
920   }
921 
922   Status = gBS->InstallProtocolInterface (
923                   &Controller,
924                   &gEfiExtScsiPassThruProtocolGuid,
925                   EFI_NATIVE_INTERFACE,
926                   &(Private->ExtScsiPassThru)
927                   );
928   ASSERT_EFI_ERROR (Status);
929 
930   return EFI_SUCCESS;
931 
932 Error:
933   if (Private != NULL) {
934     if (Private->TmrlMapping != NULL) {
935       UfsHc->Unmap (UfsHc, Private->TmrlMapping);
936     }
937     if (Private->UtpTmrlBase != NULL) {
938       UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
939     }
940 
941     if (Private->TrlMapping != NULL) {
942       UfsHc->Unmap (UfsHc, Private->TrlMapping);
943     }
944     if (Private->UtpTrlBase != NULL) {
945       UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
946     }
947 
948     if (Private->TimerEvent != NULL) {
949       gBS->CloseEvent (Private->TimerEvent);
950     }
951 
952     FreePool (Private);
953   }
954 
955   if (UfsHc != NULL) {
956     gBS->CloseProtocol (
957            Controller,
958            &gEdkiiUfsHostControllerProtocolGuid,
959            This->DriverBindingHandle,
960            Controller
961            );
962   }
963 
964   return Status;
965 }
966 
967 /**
968   Stops a device controller or a bus controller.
969 
970   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
971   As a result, much of the error checking on the parameters to Stop() has been moved
972   into this common boot service. It is legal to call Stop() from other locations,
973   but the following calling restrictions must be followed or the system behavior will not be deterministic.
974   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
975      same driver's Start() function.
976   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
977      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
978      Start() function, and the Start() function must have called OpenProtocol() on
979      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
980 
981   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
982   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
983                                 support a bus specific I/O protocol for the driver
984                                 to use to stop the device.
985   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
986   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
987                                 if NumberOfChildren is 0.
988 
989   @retval EFI_SUCCESS           The device was stopped.
990   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
991 
992 **/
993 EFI_STATUS
994 EFIAPI
UfsPassThruDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)995 UfsPassThruDriverBindingStop (
996   IN  EFI_DRIVER_BINDING_PROTOCOL       *This,
997   IN  EFI_HANDLE                        Controller,
998   IN  UINTN                             NumberOfChildren,
999   IN  EFI_HANDLE                        *ChildHandleBuffer
1000   )
1001 {
1002   EFI_STATUS                            Status;
1003   UFS_PASS_THRU_PRIVATE_DATA            *Private;
1004   EFI_EXT_SCSI_PASS_THRU_PROTOCOL       *ExtScsiPassThru;
1005   EDKII_UFS_HOST_CONTROLLER_PROTOCOL    *UfsHc;
1006   UFS_PASS_THRU_TRANS_REQ               *TransReq;
1007   LIST_ENTRY                            *Entry;
1008   LIST_ENTRY                            *NextEntry;
1009 
1010   DEBUG ((EFI_D_INFO, "==UfsPassThru Stop== Controller Controller = %x\n", Controller));
1011 
1012   Status = gBS->OpenProtocol (
1013                   Controller,
1014                   &gEfiExtScsiPassThruProtocolGuid,
1015                   (VOID **) &ExtScsiPassThru,
1016                   This->DriverBindingHandle,
1017                   Controller,
1018                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
1019                   );
1020 
1021   if (EFI_ERROR (Status)) {
1022     return EFI_DEVICE_ERROR;
1023   }
1024 
1025   Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (ExtScsiPassThru);
1026   UfsHc   = Private->UfsHostController;
1027 
1028   //
1029   // Cleanup the resources of I/O requests in the async I/O queue
1030   //
1031   if (!IsListEmpty(&Private->Queue)) {
1032     EFI_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
1033       TransReq  = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
1034 
1035       //
1036       // TODO: Should find/add a proper host adapter return status for this
1037       // case.
1038       //
1039       TransReq->Packet->HostAdapterStatus =
1040         EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
1041 
1042       SignalCallerEvent (Private, TransReq);
1043     }
1044   }
1045 
1046   Status = gBS->UninstallProtocolInterface (
1047                   Controller,
1048                   &gEfiExtScsiPassThruProtocolGuid,
1049                   &(Private->ExtScsiPassThru)
1050                   );
1051 
1052   if (EFI_ERROR (Status)) {
1053     return EFI_DEVICE_ERROR;
1054   }
1055 
1056   //
1057   // Stop Ufs Host Controller
1058   //
1059   Status = UfsControllerStop (Private);
1060   ASSERT_EFI_ERROR (Status);
1061 
1062   if (Private->TmrlMapping != NULL) {
1063     UfsHc->Unmap (UfsHc, Private->TmrlMapping);
1064   }
1065   if (Private->UtpTmrlBase != NULL) {
1066     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
1067   }
1068 
1069   if (Private->TrlMapping != NULL) {
1070     UfsHc->Unmap (UfsHc, Private->TrlMapping);
1071   }
1072   if (Private->UtpTrlBase != NULL) {
1073     UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
1074   }
1075 
1076   if (Private->TimerEvent != NULL) {
1077     gBS->CloseEvent (Private->TimerEvent);
1078   }
1079 
1080   FreePool (Private);
1081 
1082   //
1083   // Close protocols opened by UfsPassThru controller driver
1084   //
1085   gBS->CloseProtocol (
1086          Controller,
1087          &gEdkiiUfsHostControllerProtocolGuid,
1088          This->DriverBindingHandle,
1089          Controller
1090          );
1091 
1092   return Status;
1093 }
1094 
1095 
1096 /**
1097   The user Entry Point for module UfsPassThru. The user code starts with this function.
1098 
1099   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
1100   @param[in] SystemTable    A pointer to the EFI System Table.
1101 
1102   @retval EFI_SUCCESS       The entry point is executed successfully.
1103   @retval other             Some error occurs when executing this entry point.
1104 
1105 **/
1106 EFI_STATUS
1107 EFIAPI
InitializeUfsPassThru(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)1108 InitializeUfsPassThru (
1109   IN EFI_HANDLE           ImageHandle,
1110   IN EFI_SYSTEM_TABLE     *SystemTable
1111   )
1112 {
1113   EFI_STATUS              Status;
1114 
1115   //
1116   // Install driver model protocol(s).
1117   //
1118   Status = EfiLibInstallDriverBindingComponentName2 (
1119              ImageHandle,
1120              SystemTable,
1121              &gUfsPassThruDriverBinding,
1122              ImageHandle,
1123              &gUfsPassThruComponentName,
1124              &gUfsPassThruComponentName2
1125              );
1126   ASSERT_EFI_ERROR (Status);
1127 
1128   return Status;
1129 }
1130