TianoCore EDK2 master
Loading...
Searching...
No Matches
UfsPassThru.c
Go to the documentation of this file.
1
9#include "UfsPassThru.h"
10
11//
12// Template for Ufs Pass Thru private data.
13//
14UFS_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,
31 },
32 { // UfsDevConfig
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
73EFI_DRIVER_BINDING_PROTOCOL gUfsPassThruDriverBinding = {
77 0x10,
78 NULL,
79 NULL
80};
81
82UFS_DEVICE_PATH mUfsDevicePathTemplate = {
83 {
86 {
87 (UINT8)(sizeof (UFS_DEVICE_PATH)),
88 (UINT8)((sizeof (UFS_DEVICE_PATH)) >> 8)
89 }
90 },
91 0,
92 0
93};
94
95UINT8 mUfsTargetId[TARGET_MAX_BYTES];
96
98
141EFIAPI
144 IN UINT8 *Target,
145 IN UINT64 Lun,
147 IN EFI_EVENT Event OPTIONAL
148 )
149{
150 EFI_STATUS Status;
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 {
167 return EFI_INVALID_PARAMETER;
168 }
169
170 if ((Packet->SenseDataLength != 0) && (Packet->SenseData == NULL)) {
171 return EFI_INVALID_PARAMETER;
172 }
173
174 if ((This->Mode->IoAlign > 1) && !ADDRESS_IS_ALIGNED (Packet->InDataBuffer, This->Mode->IoAlign)) {
175 return EFI_INVALID_PARAMETER;
176 }
177
178 if ((This->Mode->IoAlign > 1) && !ADDRESS_IS_ALIGNED (Packet->OutDataBuffer, This->Mode->IoAlign)) {
179 return EFI_INVALID_PARAMETER;
180 }
181
182 if ((This->Mode->IoAlign > 1) && !ADDRESS_IS_ALIGNED (Packet->SenseData, This->Mode->IoAlign)) {
183 return EFI_INVALID_PARAMETER;
184 }
185
186 //
187 // For UFS 2.0 compatible device, 0 is always used to represent the location of the UFS device.
188 //
189 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
190 if ((Target == NULL) || (CompareMem (Target, mUfsTargetId, TARGET_MAX_BYTES) != 0)) {
191 return EFI_INVALID_PARAMETER;
192 }
193
194 //
195 // UFS 2.0 spec Section 10.6.7 - Translation of 8-bit UFS LUN to 64-bit SCSI LUN Address
196 // 0xC1 in the first 8 bits of the 64-bit address indicates a well known LUN address in the SAM SCSI format.
197 // The second 8 bits of the 64-bit address saves the corresponding 8-bit UFS LUN.
198 //
199 if ((UINT8)Lun == UFS_WLUN_PREFIX) {
200 UfsLun = BIT7 | (((UINT8 *)&Lun)[1] & 0xFF);
201 } else if ((UINT8)Lun == 0) {
202 UfsLun = ((UINT8 *)&Lun)[1] & 0xFF;
203 } else {
204 return EFI_INVALID_PARAMETER;
205 }
206
207 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
208 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
209 continue;
210 }
211
212 if (Private->Luns.Lun[Index] == UfsLun) {
213 break;
214 }
215 }
216
217 if (Index == UFS_MAX_LUNS) {
218 return EFI_INVALID_PARAMETER;
219 }
220
221 Status = UfsExecScsiCmds (Private, UfsLun, Packet, Event);
222
223 return Status;
224}
225
253EFIAPI
256 IN OUT UINT8 **Target,
257 IN OUT UINT64 *Lun
258 )
259{
261 UINT8 UfsLun;
262 UINT16 Index;
263 UINT16 Next;
264
265 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
266
267 if ((Target == NULL) || (Lun == NULL)) {
268 return EFI_INVALID_PARAMETER;
269 }
270
271 if (*Target == NULL) {
272 return EFI_INVALID_PARAMETER;
273 }
274
275 UfsLun = 0;
276 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0xFF);
277 if (CompareMem (*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
278 //
279 // If the array is all 0xFF's, return the first exposed Lun to caller.
280 //
281 SetMem (*Target, TARGET_MAX_BYTES, 0x00);
282 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
283 if ((Private->Luns.BitMask & (BIT0 << Index)) != 0) {
284 UfsLun = Private->Luns.Lun[Index];
285 break;
286 }
287 }
288
289 if (Index != UFS_MAX_LUNS) {
290 *Lun = 0;
291 if ((UfsLun & BIT7) == BIT7) {
292 ((UINT8 *)Lun)[0] = UFS_WLUN_PREFIX;
293 ((UINT8 *)Lun)[1] = UfsLun & ~BIT7;
294 } else {
295 ((UINT8 *)Lun)[1] = UfsLun;
296 }
297
298 return EFI_SUCCESS;
299 } else {
300 return EFI_NOT_FOUND;
301 }
302 }
303
304 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
305 if (CompareMem (*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
306 if (((UINT8 *)Lun)[0] == UFS_WLUN_PREFIX) {
307 UfsLun = BIT7 | (((UINT8 *)Lun)[1] & 0xFF);
308 } else if (((UINT8 *)Lun)[0] == 0) {
309 UfsLun = ((UINT8 *)Lun)[1] & 0xFF;
310 } else {
311 return EFI_NOT_FOUND;
312 }
313
314 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
315 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
316 continue;
317 }
318
319 if (Private->Luns.Lun[Index] != UfsLun) {
320 continue;
321 }
322
323 for (Next = Index + 1; Next < UFS_MAX_LUNS; Next++) {
324 if ((Private->Luns.BitMask & (BIT0 << Next)) != 0) {
325 UfsLun = Private->Luns.Lun[Next];
326 break;
327 }
328 }
329
330 if (Next == UFS_MAX_LUNS) {
331 return EFI_NOT_FOUND;
332 } else {
333 break;
334 }
335 }
336
337 if (Index != UFS_MAX_LUNS) {
338 *Lun = 0;
339 if ((UfsLun & BIT7) == BIT7) {
340 ((UINT8 *)Lun)[0] = UFS_WLUN_PREFIX;
341 ((UINT8 *)Lun)[1] = UfsLun & ~BIT7;
342 } else {
343 ((UINT8 *)Lun)[1] = UfsLun;
344 }
345
346 return EFI_SUCCESS;
347 } else {
348 return EFI_NOT_FOUND;
349 }
350 }
351
352 return EFI_NOT_FOUND;
353}
354
383EFIAPI
386 IN UINT8 *Target,
387 IN UINT64 Lun,
388 IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
389 )
390{
392 EFI_DEV_PATH *DevicePathNode;
393 UINT8 UfsLun;
394 UINT16 Index;
395
396 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
397
398 //
399 // Validate parameters passed in.
400 //
401 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0x00);
402 if (CompareMem (Target, mUfsTargetId, TARGET_MAX_BYTES) != 0) {
403 return EFI_INVALID_PARAMETER;
404 }
405
406 if ((UINT8)Lun == UFS_WLUN_PREFIX) {
407 UfsLun = BIT7 | (((UINT8 *)&Lun)[1] & 0xFF);
408 } else if ((UINT8)Lun == 0) {
409 UfsLun = ((UINT8 *)&Lun)[1] & 0xFF;
410 } else {
411 return EFI_NOT_FOUND;
412 }
413
414 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
415 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
416 continue;
417 }
418
419 if (Private->Luns.Lun[Index] == UfsLun) {
420 break;
421 }
422 }
423
424 if (Index == UFS_MAX_LUNS) {
425 return EFI_NOT_FOUND;
426 }
427
428 DevicePathNode = AllocateCopyPool (sizeof (UFS_DEVICE_PATH), &mUfsDevicePathTemplate);
429 if (DevicePathNode == NULL) {
430 return EFI_OUT_OF_RESOURCES;
431 }
432
433 DevicePathNode->Ufs.Pun = 0;
434 DevicePathNode->Ufs.Lun = UfsLun;
435
436 *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)DevicePathNode;
437
438 return EFI_SUCCESS;
439}
440
461EFIAPI
464 IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
465 OUT UINT8 **Target,
466 OUT UINT64 *Lun
467 )
468{
470 EFI_DEV_PATH *DevicePathNode;
471 UINT8 Pun;
472 UINT8 UfsLun;
473 UINT16 Index;
474
475 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (This);
476
477 //
478 // Validate parameters passed in.
479 //
480 if ((DevicePath == NULL) || (Target == NULL) || (Lun == NULL)) {
481 return EFI_INVALID_PARAMETER;
482 }
483
484 if (*Target == NULL) {
485 return EFI_INVALID_PARAMETER;
486 }
487
488 //
489 // Check whether the DevicePath belongs to UFS_DEVICE_PATH
490 //
491 if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || (DevicePath->SubType != MSG_UFS_DP) ||
492 (DevicePathNodeLength (DevicePath) != sizeof (UFS_DEVICE_PATH)))
493 {
494 return EFI_UNSUPPORTED;
495 }
496
497 DevicePathNode = (EFI_DEV_PATH *)DevicePath;
498
499 Pun = (UINT8)DevicePathNode->Ufs.Pun;
500 UfsLun = (UINT8)DevicePathNode->Ufs.Lun;
501
502 if (Pun != 0) {
503 return EFI_NOT_FOUND;
504 }
505
506 for (Index = 0; Index < UFS_MAX_LUNS; Index++) {
507 if ((Private->Luns.BitMask & (BIT0 << Index)) == 0) {
508 continue;
509 }
510
511 if (Private->Luns.Lun[Index] == UfsLun) {
512 break;
513 }
514 }
515
516 if (Index == UFS_MAX_LUNS) {
517 return EFI_NOT_FOUND;
518 }
519
520 SetMem (*Target, TARGET_MAX_BYTES, 0x00);
521 *Lun = 0;
522 if ((UfsLun & BIT7) == BIT7) {
523 ((UINT8 *)Lun)[0] = UFS_WLUN_PREFIX;
524 ((UINT8 *)Lun)[1] = UfsLun & ~BIT7;
525 } else {
526 ((UINT8 *)Lun)[1] = UfsLun;
527 }
528
529 return EFI_SUCCESS;
530}
531
544EFIAPI
547 )
548{
549 //
550 // Return success directly then upper layer driver could think reset channel operation is done.
551 //
552 return EFI_SUCCESS;
553}
554
575EFIAPI
578 IN UINT8 *Target,
579 IN UINT64 Lun
580 )
581{
582 //
583 // Return success directly then upper layer driver could think reset target LUN operation is done.
584 //
585 return EFI_SUCCESS;
586}
587
611EFIAPI
614 IN OUT UINT8 **Target
615 )
616{
617 if ((Target == NULL) || (*Target == NULL)) {
618 return EFI_INVALID_PARAMETER;
619 }
620
621 SetMem (mUfsTargetId, TARGET_MAX_BYTES, 0xFF);
622 if (CompareMem (*Target, mUfsTargetId, TARGET_MAX_BYTES) == 0) {
623 SetMem (*Target, TARGET_MAX_BYTES, 0x00);
624 return EFI_SUCCESS;
625 }
626
627 return EFI_NOT_FOUND;
628}
629
673EFIAPI
676 IN EFI_HANDLE Controller,
677 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
678 )
679{
680 EFI_STATUS Status;
681 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
682 EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHostController;
683
684 //
685 // Ufs Pass Thru driver is a device driver, and should ingore the
686 // "RemainingDevicePath" according to UEFI spec
687 //
688 Status = gBS->OpenProtocol (
689 Controller,
690 &gEfiDevicePathProtocolGuid,
691 (VOID *)&ParentDevicePath,
692 This->DriverBindingHandle,
693 Controller,
694 EFI_OPEN_PROTOCOL_BY_DRIVER
695 );
696 if (EFI_ERROR (Status)) {
697 //
698 // EFI_ALREADY_STARTED is also an error
699 //
700 return Status;
701 }
702
703 //
704 // Close the protocol because we don't use it here
705 //
706 gBS->CloseProtocol (
707 Controller,
708 &gEfiDevicePathProtocolGuid,
709 This->DriverBindingHandle,
710 Controller
711 );
712
713 Status = gBS->OpenProtocol (
714 Controller,
716 (VOID **)&UfsHostController,
717 This->DriverBindingHandle,
718 Controller,
719 EFI_OPEN_PROTOCOL_BY_DRIVER
720 );
721
722 if (EFI_ERROR (Status)) {
723 //
724 // EFI_ALREADY_STARTED is also an error
725 //
726 return Status;
727 }
728
729 //
730 // Close the I/O Abstraction(s) used to perform the supported test
731 //
732 gBS->CloseProtocol (
733 Controller,
735 This->DriverBindingHandle,
736 Controller
737 );
738
739 return EFI_SUCCESS;
740}
741
755 )
756{
757 EFI_STATUS Status;
758 UINT8 DeviceInitStatus;
759 UINT32 Timeout;
760
761 DeviceInitStatus = 0xFF;
762 Timeout = PcdGet32 (PcdUfsInitialCompletionTimeout);
763
764 //
765 // The host enables the device initialization completion by setting fDeviceInit flag.
766 //
767 Status = UfsSetFlag (Private, UfsFlagDevInit);
768 if (EFI_ERROR (Status)) {
769 return Status;
770 }
771
772 do {
773 Status = UfsReadFlag (Private, UfsFlagDevInit, &DeviceInitStatus);
774 if (EFI_ERROR (Status)) {
775 return Status;
776 }
777
779 Timeout--;
780 } while (DeviceInitStatus != 0 && Timeout != 0);
781
782 if (Timeout == 0) {
783 DEBUG ((DEBUG_ERROR, "UfsFinishDeviceInitialization DeviceInitStatus=%x EFI_TIMEOUT \n", DeviceInitStatus));
784 return EFI_TIMEOUT;
785 } else {
786 DEBUG ((DEBUG_INFO, "UfsFinishDeviceInitialization Timeout left=%x EFI_SUCCESS \n", Timeout));
787 return EFI_SUCCESS;
788 }
789}
790
827EFIAPI
830 IN EFI_HANDLE Controller,
831 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
832 )
833{
834 EFI_STATUS Status;
837 UINTN UfsHcBase;
838 UINT32 Index;
839 UFS_UNIT_DESC UnitDescriptor;
840 UFS_DEV_DESC DeviceDescriptor;
841 UINT32 UnitDescriptorSize;
842 UINT32 DeviceDescriptorSize;
843 EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE Attributes;
844 UINT8 RefClkAttr;
845
846 Status = EFI_SUCCESS;
847 UfsHc = NULL;
848 Private = NULL;
849 UfsHcBase = 0;
850
851 DEBUG ((DEBUG_INFO, "==UfsPassThru Start== Controller = %x\n", Controller));
852
853 Status = gBS->OpenProtocol (
854 Controller,
856 (VOID **)&UfsHc,
857 This->DriverBindingHandle,
858 Controller,
859 EFI_OPEN_PROTOCOL_BY_DRIVER
860 );
861
862 if (EFI_ERROR (Status)) {
863 DEBUG ((DEBUG_ERROR, "Open Ufs Host Controller Protocol Error, Status = %r\n", Status));
864 goto Error;
865 }
866
867 //
868 // Get the UFS Host Controller MMIO Bar Base Address.
869 //
870 Status = UfsHc->GetUfsHcMmioBar (UfsHc, &UfsHcBase);
871 if (EFI_ERROR (Status)) {
872 DEBUG ((DEBUG_ERROR, "Get Ufs Host Controller Mmio Bar Error, Status = %r\n", Status));
873 goto Error;
874 }
875
876 //
877 // Initialize Ufs Pass Thru private data for managed UFS Host Controller.
878 //
879 Private = AllocateCopyPool (sizeof (UFS_PASS_THRU_PRIVATE_DATA), &gUfsPassThruTemplate);
880 if (Private == NULL) {
881 DEBUG ((DEBUG_ERROR, "Unable to allocate Ufs Pass Thru private data\n"));
882 Status = EFI_OUT_OF_RESOURCES;
883 goto Error;
884 }
885
886 Private->ExtScsiPassThru.Mode = &Private->ExtScsiPassThruMode;
887 Private->UfsHostController = UfsHc;
888 Private->UfsHcBase = UfsHcBase;
889 Private->Handle = Controller;
890 Private->UfsHcDriverInterface.UfsHcProtocol = UfsHc;
891 Private->UfsHcDriverInterface.UfsExecUicCommand = UfsHcDriverInterfaceExecUicCommand;
892 InitializeListHead (&Private->Queue);
893
894 //
895 // This has to be done before initializing UfsHcInfo or calling the UfsControllerInit
896 //
897 if (mUfsHcPlatform == NULL) {
898 Status = gBS->LocateProtocol (&gEdkiiUfsHcPlatformProtocolGuid, NULL, (VOID **)&mUfsHcPlatform);
899 if (EFI_ERROR (Status)) {
900 DEBUG ((DEBUG_INFO, "No UfsHcPlatformProtocol present\n"));
901 }
902 }
903
904 Status = GetUfsHcInfo (Private);
905 if (EFI_ERROR (Status)) {
906 DEBUG ((DEBUG_ERROR, "Failed to initialize UfsHcInfo\n"));
907 goto Error;
908 }
909
910 //
911 // Initialize UFS Host Controller H/W.
912 //
913 Status = UfsControllerInit (Private);
914 if (EFI_ERROR (Status)) {
915 DEBUG ((DEBUG_ERROR, "Ufs Host Controller Initialization Error, Status = %r\n", Status));
916 goto Error;
917 }
918
919 //
920 // UFS 2.0 spec Section 13.1.3.3:
921 // At the end of the UFS Interconnect Layer initialization on both host and device side,
922 // the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.
923 //
924 Status = UfsExecNopCmds (Private);
925 if (EFI_ERROR (Status)) {
926 DEBUG ((DEBUG_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));
927 goto Error;
928 }
929
930 Status = UfsFinishDeviceInitialization (Private);
931 if (EFI_ERROR (Status)) {
932 DEBUG ((DEBUG_ERROR, "Device failed to finish initialization, Status = %r\n", Status));
933 goto Error;
934 }
935
936 if ((mUfsHcPlatform != NULL) &&
937 ((mUfsHcPlatform->RefClkFreq == EdkiiUfsCardRefClkFreq19p2Mhz) ||
938 (mUfsHcPlatform->RefClkFreq == EdkiiUfsCardRefClkFreq26Mhz) ||
939 (mUfsHcPlatform->RefClkFreq == EdkiiUfsCardRefClkFreq38p4Mhz)))
940 {
941 RefClkAttr = UfsAttrRefClkFreq;
942 Attributes = EdkiiUfsCardRefClkFreqObsolete;
943 Status = UfsRwAttributes (Private, TRUE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
944 if (!EFI_ERROR (Status)) {
945 if (Attributes != mUfsHcPlatform->RefClkFreq) {
946 Attributes = mUfsHcPlatform->RefClkFreq;
947 DEBUG (
948 (DEBUG_INFO,
949 "Setting bRefClkFreq attribute(%x) to %x\n 0 -> 19.2 Mhz\n 1 -> 26 Mhz\n 2 -> 38.4 Mhz\n 3 -> Obsolete\n",
950 RefClkAttr,
951 Attributes)
952 );
953 Status = UfsRwAttributes (Private, FALSE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
954 if (EFI_ERROR (Status)) {
955 DEBUG (
956 (DEBUG_ERROR,
957 "Failed to Change Reference Clock Attribute to %d, Status = %r \n",
958 mUfsHcPlatform->RefClkFreq,
959 Status)
960 );
961 }
962 }
963 } else {
964 DEBUG (
965 (DEBUG_ERROR,
966 "Failed to Read Reference Clock Attribute, Status = %r \n",
967 Status)
968 );
969 }
970 }
971
972 if ((mUfsHcPlatform != NULL) && (mUfsHcPlatform->Callback != NULL)) {
973 Status = mUfsHcPlatform->Callback (Private->Handle, EdkiiUfsHcPostLinkStartup, &Private->UfsHcDriverInterface);
974 if (EFI_ERROR (Status)) {
975 DEBUG (
976 (DEBUG_ERROR,
977 "Failure from platform driver during EdkiiUfsHcPostLinkStartup, Status = %r\n",
978 Status)
979 );
980 return Status;
981 }
982 }
983
984 //
985 // Check if 8 common luns are active and set corresponding bit mask.
986 //
987 UnitDescriptorSize = sizeof (UFS_UNIT_DESC);
988 for (Index = 0; Index < 8; Index++) {
989 Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8)Index, 0, &UnitDescriptor, &UnitDescriptorSize);
990 if (EFI_ERROR (Status)) {
991 DEBUG ((DEBUG_ERROR, "Failed to read unit descriptor, index = %X, status = %r\n", Index, Status));
992 continue;
993 }
994
995 if (UnitDescriptor.LunEn == 0x1) {
996 DEBUG ((DEBUG_INFO, "UFS LUN %X is enabled\n", Index));
997 Private->Luns.BitMask |= (BIT0 << Index);
998 }
999 }
1000
1001 //
1002 // Check if RPMB WLUN is supported and set corresponding bit mask.
1003 //
1004 DeviceDescriptorSize = sizeof (UFS_DEV_DESC);
1005 Status = UfsRwDeviceDesc (Private, TRUE, UfsDeviceDesc, 0, 0, &DeviceDescriptor, &DeviceDescriptorSize);
1006 if (EFI_ERROR (Status)) {
1007 DEBUG ((DEBUG_ERROR, "Failed to read device descriptor, status = %r\n", Status));
1008 } else {
1009 if (DeviceDescriptor.SecurityLun == 0x1) {
1010 DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
1011 Private->Luns.BitMask |= BIT11;
1012 }
1013 }
1014
1015 //
1016 // Start the asynchronous interrupt monitor
1017 //
1018 Status = gBS->CreateEvent (
1019 EVT_TIMER | EVT_NOTIFY_SIGNAL,
1020 TPL_NOTIFY,
1022 Private,
1023 &Private->TimerEvent
1024 );
1025 if (EFI_ERROR (Status)) {
1026 DEBUG ((DEBUG_ERROR, "Ufs Create Async Tasks Event Error, Status = %r\n", Status));
1027 goto Error;
1028 }
1029
1030 Status = gBS->SetTimer (
1031 Private->TimerEvent,
1033 UFS_HC_ASYNC_TIMER
1034 );
1035 if (EFI_ERROR (Status)) {
1036 DEBUG ((DEBUG_ERROR, "Ufs Set Periodic Timer Error, Status = %r\n", Status));
1037 goto Error;
1038 }
1039
1040 Status = gBS->InstallMultipleProtocolInterfaces (
1041 &Controller,
1042 &gEfiExtScsiPassThruProtocolGuid,
1043 &(Private->ExtScsiPassThru),
1045 &(Private->UfsDevConfig),
1046 NULL
1047 );
1048 ASSERT_EFI_ERROR (Status);
1049
1050 return EFI_SUCCESS;
1051
1052Error:
1053 if (Private != NULL) {
1054 if (Private->TmrlMapping != NULL) {
1055 UfsHc->Unmap (UfsHc, Private->TmrlMapping);
1056 }
1057
1058 if (Private->UtpTmrlBase != NULL) {
1059 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
1060 }
1061
1062 if (Private->TrlMapping != NULL) {
1063 UfsHc->Unmap (UfsHc, Private->TrlMapping);
1064 }
1065
1066 if (Private->UtpTrlBase != NULL) {
1067 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
1068 }
1069
1070 if (Private->TimerEvent != NULL) {
1071 gBS->CloseEvent (Private->TimerEvent);
1072 }
1073
1074 FreePool (Private);
1075 }
1076
1077 if (UfsHc != NULL) {
1078 gBS->CloseProtocol (
1079 Controller,
1081 This->DriverBindingHandle,
1082 Controller
1083 );
1084 }
1085
1086 return Status;
1087}
1088
1116EFIAPI
1119 IN EFI_HANDLE Controller,
1120 IN UINTN NumberOfChildren,
1121 IN EFI_HANDLE *ChildHandleBuffer
1122 )
1123{
1124 EFI_STATUS Status;
1126 EFI_EXT_SCSI_PASS_THRU_PROTOCOL *ExtScsiPassThru;
1128 UFS_PASS_THRU_TRANS_REQ *TransReq;
1129 LIST_ENTRY *Entry;
1130 LIST_ENTRY *NextEntry;
1131
1132 DEBUG ((DEBUG_INFO, "==UfsPassThru Stop== Controller Controller = %x\n", Controller));
1133
1134 Status = gBS->OpenProtocol (
1135 Controller,
1136 &gEfiExtScsiPassThruProtocolGuid,
1137 (VOID **)&ExtScsiPassThru,
1138 This->DriverBindingHandle,
1139 Controller,
1140 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1141 );
1142
1143 if (EFI_ERROR (Status)) {
1144 return EFI_DEVICE_ERROR;
1145 }
1146
1147 Private = UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS (ExtScsiPassThru);
1148 UfsHc = Private->UfsHostController;
1149
1150 //
1151 // Cleanup the resources of I/O requests in the async I/O queue
1152 //
1153 if (!IsListEmpty (&Private->Queue)) {
1154 BASE_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->Queue) {
1155 TransReq = UFS_PASS_THRU_TRANS_REQ_FROM_THIS (Entry);
1156
1157 //
1158 // TODO: Should find/add a proper host adapter return status for this
1159 // case.
1160 //
1161 TransReq->Packet->HostAdapterStatus =
1162 EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR;
1163
1164 SignalCallerEvent (Private, TransReq);
1165 }
1166 }
1167
1168 Status = gBS->UninstallMultipleProtocolInterfaces (
1169 Controller,
1170 &gEfiExtScsiPassThruProtocolGuid,
1171 &(Private->ExtScsiPassThru),
1173 &(Private->UfsDevConfig),
1174 NULL
1175 );
1176
1177 if (EFI_ERROR (Status)) {
1178 return EFI_DEVICE_ERROR;
1179 }
1180
1181 //
1182 // Stop Ufs Host Controller
1183 //
1184 Status = UfsControllerStop (Private);
1185 ASSERT_EFI_ERROR (Status);
1186
1187 if (Private->TmrlMapping != NULL) {
1188 UfsHc->Unmap (UfsHc, Private->TmrlMapping);
1189 }
1190
1191 if (Private->UtpTmrlBase != NULL) {
1192 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)), Private->UtpTmrlBase);
1193 }
1194
1195 if (Private->TrlMapping != NULL) {
1196 UfsHc->Unmap (UfsHc, Private->TrlMapping);
1197 }
1198
1199 if (Private->UtpTrlBase != NULL) {
1200 UfsHc->FreeBuffer (UfsHc, EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TMRD)), Private->UtpTrlBase);
1201 }
1202
1203 if (Private->TimerEvent != NULL) {
1204 gBS->CloseEvent (Private->TimerEvent);
1205 }
1206
1207 FreePool (Private);
1208
1209 //
1210 // Close protocols opened by UfsPassThru controller driver
1211 //
1212 gBS->CloseProtocol (
1213 Controller,
1215 This->DriverBindingHandle,
1216 Controller
1217 );
1218
1219 return Status;
1220}
1221
1233EFIAPI
1235 IN EFI_HANDLE ImageHandle,
1236 IN EFI_SYSTEM_TABLE *SystemTable
1237 )
1238{
1239 EFI_STATUS Status;
1240
1241 //
1242 // Install driver model protocol(s).
1243 //
1245 ImageHandle,
1246 SystemTable,
1247 &gUfsPassThruDriverBinding,
1248 ImageHandle,
1249 &gUfsPassThruComponentName,
1250 &gUfsPassThruComponentName2
1251 );
1252 ASSERT_EFI_ERROR (Status);
1253
1254 return Status;
1255}
UINT64 UINTN
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
BOOLEAN EFIAPI IsListEmpty(IN CONST LIST_ENTRY *ListHead)
Definition: LinkedList.c:403
#define BASE_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead)
Definition: BaseLib.h:2929
LIST_ENTRY *EFIAPI InitializeListHead(IN OUT LIST_ENTRY *ListHead)
Definition: LinkedList.c:182
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI SetMem(OUT VOID *Buffer, IN UINTN Length, IN UINT8 Value)
Definition: SetMemWrapper.c:38
#define MSG_UFS_DP
Definition: DevicePath.h:891
#define MESSAGING_DEVICE_PATH
Definition: DevicePath.h:321
UINTN EFIAPI DevicePathNodeLength(IN CONST VOID *Node)
VOID EFIAPI FreePool(IN VOID *Buffer)
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
#define NULL
Definition: Base.h:319
#define ADDRESS_IS_ALIGNED(Address, Alignment)
Definition: Base.h:923
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define GLOBAL_REMOVE_IF_UNREFERENCED
Definition: Base.h:48
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define DEBUG(Expression)
Definition: DebugLib.h:434
VOID EFIAPI ProcessAsyncTaskList(IN EFI_EVENT Event, IN VOID *Context)
Definition: NvmExpress.c:567
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
EFI_GUID gEdkiiUfsHostControllerProtocolGuid
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
VOID * EFI_HANDLE
Definition: UefiBaseType.h:33
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
EFI_STATUS EFIAPI EfiLibInstallDriverBindingComponentName2(IN CONST EFI_HANDLE ImageHandle, IN CONST EFI_SYSTEM_TABLE *SystemTable, IN EFI_DRIVER_BINDING_PROTOCOL *DriverBinding, IN EFI_HANDLE DriverBindingHandle, IN CONST EFI_COMPONENT_NAME_PROTOCOL *ComponentName OPTIONAL, IN CONST EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2 OPTIONAL)
@ TimerPeriodic
Definition: UefiSpec.h:535
EFI_STATUS UfsRwDeviceDesc(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN BOOLEAN Read, IN UINT8 DescId, IN UINT8 Index, IN UINT8 Selector, IN OUT VOID *Descriptor, IN UINT32 DescSize)
Definition: UfsHci.c:960
EFI_STATUS UfsRwAttributes(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN BOOLEAN Read, IN UINT8 AttrId, IN UINT8 Index, IN UINT8 Selector, IN OUT UINT32 *Attributes)
Definition: UfsHci.c:1014
EFI_STATUS UfsReadFlag(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINT8 FlagId, OUT UINT8 *Value)
Definition: UfsHci.c:1144
EFI_STATUS UfsExecNopCmds(IN UFS_PEIM_HC_PRIVATE_DATA *Private)
Definition: UfsHci.c:1171
EFI_STATUS UfsControllerInit(IN EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi, IN UFS_PEIM_HC_PRIVATE_DATA *Private)
Definition: UfsHci.c:1726
EFI_STATUS UfsControllerStop(IN UFS_PEIM_HC_PRIVATE_DATA *Private)
Definition: UfsHci.c:1781
EFI_STATUS UfsSetFlag(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINT8 FlagId)
Definition: UfsHci.c:1117
EFI_STATUS UfsExecScsiCmds(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINT8 Lun, IN OUT UFS_SCSI_REQUEST_PACKET *Packet)
Definition: UfsHci.c:1251
EFI_STATUS EFIAPI UfsRwUfsAttribute(IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This, IN BOOLEAN Read, IN UINT8 AttrId, IN UINT8 Index, IN UINT8 Selector, IN OUT UINT8 *Attribute, IN OUT UINT32 *AttrSize)
EFI_STATUS EFIAPI UfsRwUfsFlag(IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This, IN BOOLEAN Read, IN UINT8 FlagId, IN OUT UINT8 *Flag)
EFI_STATUS EFIAPI UfsRwUfsDescriptor(IN EFI_UFS_DEVICE_CONFIG_PROTOCOL *This, IN BOOLEAN Read, IN UINT8 DescId, IN UINT8 Index, IN UINT8 Selector, IN OUT UINT8 *Descriptor, IN OUT UINT32 *DescSize)
EFI_GUID gEfiUfsDeviceConfigProtocolGuid
EFI_STATUS EFIAPI UfsPassThruGetNextTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN OUT UINT8 **Target, IN OUT UINT64 *Lun)
Definition: UfsPassThru.c:254
EFI_STATUS EFIAPI InitializeUfsPassThru(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
Definition: UfsPassThru.c:1234
EFI_STATUS EFIAPI UfsPassThruResetTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN UINT8 *Target, IN UINT64 Lun)
Definition: UfsPassThru.c:576
EFI_STATUS 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)
Definition: UfsPassThru.c:142
EFI_STATUS EFIAPI UfsPassThruBuildDevicePath(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN UINT8 *Target, IN UINT64 Lun, IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath)
Definition: UfsPassThru.c:384
EFI_STATUS EFIAPI UfsPassThruGetTargetLun(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, OUT UINT8 **Target, OUT UINT64 *Lun)
Definition: UfsPassThru.c:462
EFI_STATUS UfsFinishDeviceInitialization(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
Definition: UfsPassThru.c:753
EFI_STATUS EFIAPI UfsPassThruGetNextTarget(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, IN OUT UINT8 **Target)
Definition: UfsPassThru.c:612
EFI_STATUS EFIAPI UfsPassThruDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: UfsPassThru.c:828
EFI_STATUS EFIAPI UfsPassThruResetChannel(IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This)
Definition: UfsPassThru.c:545
EFI_STATUS EFIAPI UfsPassThruDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer)
Definition: UfsPassThru.c:1117
EFI_STATUS EFIAPI UfsPassThruDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath)
Definition: UfsPassThru.c:674
EFI_STATUS GetUfsHcInfo(IN UFS_PASS_THRU_PRIVATE_DATA *Private)
EFI_STATUS EFIAPI UfsHcDriverInterfaceExecUicCommand(IN EDKII_UFS_HC_DRIVER_INTERFACE *This, IN OUT EDKII_UIC_COMMAND *UicCommand)
VOID EFIAPI SignalCallerEvent(IN UFS_PASS_THRU_PRIVATE_DATA *Private, IN UFS_PASS_THRU_TRANS_REQ *TransReq)
EDKII_UFS_EXEC_UIC_COMMAND UfsExecUicCommand
EDKII_UFS_HOST_CONTROLLER_PROTOCOL * UfsHcProtocol
EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE RefClkFreq
EDKII_UFS_HC_PLATFORM_CALLBACK Callback
EFI_EXT_SCSI_PASS_THRU_MODE * Mode