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