TianoCore EDK2 master
Loading...
Searching...
No Matches
UfsBlockIoPei.c
Go to the documentation of this file.
1
8#include "UfsBlockIoPei.h"
9
10//
11// Template for UFS HC Peim Private Data.
12//
13UFS_PEIM_HC_PRIVATE_DATA gUfsHcPeimTemplate = {
14 UFS_PEIM_HC_SIG, // Signature
15 NULL, // Controller
16 NULL, // Pool
17 { // BlkIoPpi
21 },
22 { // BlkIo2Ppi
23 EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,
27 },
28 { // BlkIoPpiList
29 EFI_PEI_PPI_DESCRIPTOR_PPI,
30 &gEfiPeiVirtualBlockIoPpiGuid,
31 NULL
32 },
33 { // BlkIo2PpiList
34 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
35 &gEfiPeiVirtualBlockIo2PpiGuid,
36 NULL
37 },
38 { // Media
39 {
41 FALSE,
42 TRUE,
43 FALSE,
44 0x1000,
45 0
46 },
47 {
49 FALSE,
50 TRUE,
51 FALSE,
52 0x1000,
53 0
54 },
55 {
57 FALSE,
58 TRUE,
59 FALSE,
60 0x1000,
61 0
62 },
63 {
65 FALSE,
66 TRUE,
67 FALSE,
68 0x1000,
69 0
70 },
71 {
73 FALSE,
74 TRUE,
75 FALSE,
76 0x1000,
77 0
78 },
79 {
81 FALSE,
82 TRUE,
83 FALSE,
84 0x1000,
85 0
86 },
87 {
89 FALSE,
90 TRUE,
91 FALSE,
92 0x1000,
93 0
94 },
95 {
97 FALSE,
98 TRUE,
99 FALSE,
100 0x1000,
101 0
102 }
103 },
104 { // EndOfPeiNotifyList
105 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
106 &gEfiEndOfPeiSignalPpiGuid,
108 },
109 0, // UfsHcBase
110 0, // Capabilities
111 0, // TaskTag
112 0, // UtpTrlBase
113 0, // Nutrs
114 NULL, // TrlMapping
115 0, // UtpTmrlBase
116 0, // Nutmrs
117 NULL, // TmrlMapping
118 { // Luns
119 {
120 UFS_LUN_0, // Ufs Common Lun 0
121 UFS_LUN_1, // Ufs Common Lun 1
122 UFS_LUN_2, // Ufs Common Lun 2
123 UFS_LUN_3, // Ufs Common Lun 3
124 UFS_LUN_4, // Ufs Common Lun 4
125 UFS_LUN_5, // Ufs Common Lun 5
126 UFS_LUN_6, // Ufs Common Lun 6
127 UFS_LUN_7, // Ufs Common Lun 7
128 },
129 0x0000, // By default exposing all Luns.
130 0x0
131 }
132};
133
150 IN UINTN Lun,
151 OUT VOID *SenseData OPTIONAL,
152 OUT UINT8 *SenseDataLength
153 )
154{
156 UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];
157 EFI_STATUS Status;
158
159 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
160 ZeroMem (Cdb, sizeof (Cdb));
161
162 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
163
164 Packet.Timeout = UFS_TIMEOUT;
165 Packet.Cdb = Cdb;
166 Packet.CdbLength = sizeof (Cdb);
167 Packet.DataDirection = UfsNoData;
168 Packet.SenseData = SenseData;
169 Packet.SenseDataLength = *SenseDataLength;
170
171 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
172
173 if (*SenseDataLength != 0) {
174 *SenseDataLength = Packet.SenseDataLength;
175 }
176
177 return Status;
178}
179
198 IN UINTN Lun,
199 OUT VOID *DataBuffer,
200 OUT UINT32 *DataLength,
201 OUT VOID *SenseData OPTIONAL,
202 OUT UINT8 *SenseDataLength
203 )
204{
206 UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];
207 EFI_STATUS Status;
208
209 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
210 ZeroMem (Cdb, sizeof (Cdb));
211
212 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
213
214 Packet.Timeout = UFS_TIMEOUT;
215 Packet.Cdb = Cdb;
216 Packet.CdbLength = sizeof (Cdb);
217 Packet.InDataBuffer = DataBuffer;
218 Packet.InTransferLength = *DataLength;
219 Packet.DataDirection = UfsDataIn;
220 Packet.SenseData = SenseData;
221 Packet.SenseDataLength = *SenseDataLength;
222
223 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
224
225 if (*SenseDataLength != 0) {
226 *SenseDataLength = Packet.SenseDataLength;
227 }
228
229 if (!EFI_ERROR (Status)) {
230 *DataLength = Packet.InTransferLength;
231 }
232
233 return Status;
234}
235
254 IN UINTN Lun,
255 OUT VOID *DataBuffer,
256 OUT UINT32 *DataLength,
257 OUT VOID *SenseData OPTIONAL,
258 OUT UINT8 *SenseDataLength
259 )
260{
262 UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
263 EFI_STATUS Status;
264
265 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
266 ZeroMem (Cdb, sizeof (Cdb));
267
268 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;
269 Cdb[1] = 0x10; // Service Action should be 0x10 for UFS device.
270 Cdb[13] = 0x20; // The maximum number of bytes for returned data.
271
272 Packet.Timeout = UFS_TIMEOUT;
273 Packet.Cdb = Cdb;
274 Packet.CdbLength = sizeof (Cdb);
275 Packet.InDataBuffer = DataBuffer;
276 Packet.InTransferLength = *DataLength;
277 Packet.DataDirection = UfsDataIn;
278 Packet.SenseData = SenseData;
279 Packet.SenseDataLength = *SenseDataLength;
280
281 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
282
283 if (*SenseDataLength != 0) {
284 *SenseDataLength = Packet.SenseDataLength;
285 }
286
287 if (!EFI_ERROR (Status)) {
288 *DataLength = Packet.InTransferLength;
289 }
290
291 return Status;
292}
293
314 IN UINTN Lun,
315 IN UINTN StartLba,
316 IN UINT32 SectorNum,
317 OUT VOID *DataBuffer,
318 OUT UINT32 *DataLength,
319 OUT VOID *SenseData OPTIONAL,
320 OUT UINT8 *SenseDataLength
321 )
322{
324 UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];
325 EFI_STATUS Status;
326
327 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
328 ZeroMem (Cdb, sizeof (Cdb));
329
330 Cdb[0] = EFI_SCSI_OP_READ10;
331 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 ((UINT32)StartLba));
332 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16)SectorNum));
333
334 Packet.Timeout = UFS_TIMEOUT;
335 Packet.Cdb = Cdb;
336 Packet.CdbLength = sizeof (Cdb);
337 Packet.InDataBuffer = DataBuffer;
338 Packet.InTransferLength = *DataLength;
339 Packet.DataDirection = UfsDataIn;
340 Packet.SenseData = SenseData;
341 Packet.SenseDataLength = *SenseDataLength;
342
343 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
344
345 if (*SenseDataLength != 0) {
346 *SenseDataLength = Packet.SenseDataLength;
347 }
348
349 if (!EFI_ERROR (Status)) {
350 *DataLength = Packet.InTransferLength;
351 }
352
353 return Status;
354}
355
376 IN UINTN Lun,
377 IN UINTN StartLba,
378 IN UINT32 SectorNum,
379 OUT VOID *DataBuffer,
380 OUT UINT32 *DataLength,
381 OUT VOID *SenseData OPTIONAL,
382 OUT UINT8 *SenseDataLength
383 )
384{
386 UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
387 EFI_STATUS Status;
388
389 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
390 ZeroMem (Cdb, sizeof (Cdb));
391
392 Cdb[0] = EFI_SCSI_OP_READ16;
393 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
394 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorNum));
395
396 Packet.Timeout = UFS_TIMEOUT;
397 Packet.Cdb = Cdb;
398 Packet.CdbLength = sizeof (Cdb);
399 Packet.InDataBuffer = DataBuffer;
400 Packet.InTransferLength = *DataLength;
401 Packet.DataDirection = UfsDataIn;
402 Packet.SenseData = SenseData;
403 Packet.SenseDataLength = *SenseDataLength;
404
405 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
406
407 if (*SenseDataLength != 0) {
408 *SenseDataLength = Packet.SenseDataLength;
409 }
410
411 if (!EFI_ERROR (Status)) {
412 *DataLength = Packet.InTransferLength;
413 }
414
415 return Status;
416}
417
432 IN EFI_SCSI_SENSE_DATA *SenseData,
433 OUT BOOLEAN *NeedRetry
434 )
435{
436 if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
437 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA))
438 {
439 Media->MediaPresent = FALSE;
440 *NeedRetry = FALSE;
441 DEBUG ((DEBUG_VERBOSE, "UfsBlockIoPei: Is No Media\n"));
442 return EFI_DEVICE_ERROR;
443 }
444
445 if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
446 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE))
447 {
448 *NeedRetry = TRUE;
449 DEBUG ((DEBUG_VERBOSE, "UfsBlockIoPei: Is Media Change\n"));
450 return EFI_SUCCESS;
451 }
452
453 if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
454 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_RESET))
455 {
456 *NeedRetry = TRUE;
457 DEBUG ((DEBUG_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
458 return EFI_SUCCESS;
459 }
460
461 if ((SenseData->Sense_Key == EFI_SCSI_SK_MEDIUM_ERROR) ||
462 ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
463 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN)))
464 {
465 *NeedRetry = FALSE;
466 DEBUG ((DEBUG_VERBOSE, "UfsBlockIoPei: Media Error\n"));
467 return EFI_DEVICE_ERROR;
468 }
469
470 if (SenseData->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
471 *NeedRetry = FALSE;
472 DEBUG ((DEBUG_VERBOSE, "UfsBlockIoPei: Hardware Error\n"));
473 return EFI_DEVICE_ERROR;
474 }
475
476 if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
477 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NOT_READY) &&
478 (SenseData->Addnl_Sense_Code_Qualifier == EFI_SCSI_ASCQ_IN_PROGRESS))
479 {
480 *NeedRetry = TRUE;
481 DEBUG ((DEBUG_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
482 return EFI_SUCCESS;
483 }
484
485 *NeedRetry = FALSE;
486 DEBUG ((DEBUG_VERBOSE, "UfsBlockIoPei: Sense Key = 0x%x ASC = 0x%x!\n", SenseData->Sense_Key, SenseData->Addnl_Sense_Code));
487 return EFI_DEVICE_ERROR;
488}
489
510EFIAPI
512 IN EFI_PEI_SERVICES **PeiServices,
514 OUT UINTN *NumberBlockDevices
515 )
516{
517 //
518 // For Ufs device, it has up to 8 normal Luns plus some well-known Luns.
519 // At PEI phase, we will only expose normal Luns to user.
520 // For those disabled Lun, when user try to access it, the operation would fail.
521 //
522 *NumberBlockDevices = UFS_PEIM_MAX_LUNS;
523 return EFI_SUCCESS;
524}
525
568EFIAPI
570 IN EFI_PEI_SERVICES **PeiServices,
572 IN UINTN DeviceIndex,
573 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
574 )
575{
576 EFI_STATUS Status;
578 EFI_SCSI_SENSE_DATA SenseData;
579 UINT8 SenseDataLength;
582 UINTN DataLength;
583 BOOLEAN NeedRetry;
584 UINTN Lun;
585
586 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
587 NeedRetry = TRUE;
588
589 if ((DeviceIndex == 0) || (DeviceIndex > UFS_PEIM_MAX_LUNS)) {
590 return EFI_INVALID_PARAMETER;
591 }
592
593 Lun = DeviceIndex - 1;
594 if ((Private->Luns.BitMask & (BIT0 << Lun)) == 0) {
595 return EFI_ACCESS_DENIED;
596 }
597
598 ZeroMem (&SenseData, sizeof (SenseData));
599 ZeroMem (&Capacity, sizeof (Capacity));
600 ZeroMem (&Capacity16, sizeof (Capacity16));
601 SenseDataLength = sizeof (SenseData);
602 //
603 // First test unit ready
604 //
605 do {
606 Status = UfsPeimTestUnitReady (
607 Private,
608 Lun,
609 &SenseData,
610 &SenseDataLength
611 );
612 if (!EFI_ERROR (Status)) {
613 break;
614 }
615
616 if (SenseDataLength == 0) {
617 continue;
618 }
619
620 Status = UfsPeimParsingSenseKeys (&(Private->Media[Lun]), &SenseData, &NeedRetry);
621 if (EFI_ERROR (Status)) {
622 return EFI_DEVICE_ERROR;
623 }
624 } while (NeedRetry);
625
626 DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
627 SenseDataLength = 0;
628 Status = UfsPeimReadCapacity (Private, Lun, &Capacity, (UINT32 *)&DataLength, NULL, &SenseDataLength);
629 if (EFI_ERROR (Status)) {
630 return EFI_DEVICE_ERROR;
631 }
632
633 if ((Capacity.LastLba3 == 0xff) && (Capacity.LastLba2 == 0xff) &&
634 (Capacity.LastLba1 == 0xff) && (Capacity.LastLba0 == 0xff))
635 {
636 DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA16);
637 SenseDataLength = 0;
638 Status = UfsPeimReadCapacity16 (Private, Lun, &Capacity16, (UINT32 *)&DataLength, NULL, &SenseDataLength);
639 if (EFI_ERROR (Status)) {
640 return EFI_DEVICE_ERROR;
641 }
642
643 Private->Media[Lun].LastBlock = ((UINT32)Capacity16.LastLba3 << 24) | (Capacity16.LastLba2 << 16) | (Capacity16.LastLba1 << 8) | Capacity16.LastLba0;
644 Private->Media[Lun].LastBlock |= LShiftU64 ((UINT64)Capacity16.LastLba7, 56) | LShiftU64 ((UINT64)Capacity16.LastLba6, 48) | LShiftU64 ((UINT64)Capacity16.LastLba5, 40) | LShiftU64 ((UINT64)Capacity16.LastLba4, 32);
645 Private->Media[Lun].BlockSize = (Capacity16.BlockSize3 << 24) | (Capacity16.BlockSize2 << 16) | (Capacity16.BlockSize1 << 8) | Capacity16.BlockSize0;
646 } else {
647 Private->Media[Lun].LastBlock = ((UINT32)Capacity.LastLba3 << 24) | (Capacity.LastLba2 << 16) | (Capacity.LastLba1 << 8) | Capacity.LastLba0;
648 Private->Media[Lun].BlockSize = (Capacity.BlockSize3 << 24) | (Capacity.BlockSize2 << 16) | (Capacity.BlockSize1 << 8) | Capacity.BlockSize0;
649 }
650
651 MediaInfo->DeviceType = UfsDevice;
652 MediaInfo->MediaPresent = Private->Media[Lun].MediaPresent;
653 MediaInfo->LastBlock = (UINTN)Private->Media[Lun].LastBlock;
654 MediaInfo->BlockSize = Private->Media[Lun].BlockSize;
655
656 return EFI_SUCCESS;
657}
658
694EFIAPI
696 IN EFI_PEI_SERVICES **PeiServices,
698 IN UINTN DeviceIndex,
699 IN EFI_PEI_LBA StartLBA,
700 IN UINTN BufferSize,
701 OUT VOID *Buffer
702 )
703{
704 EFI_STATUS Status;
705 UINTN BlockSize;
706 UINTN NumberOfBlocks;
708 EFI_SCSI_SENSE_DATA SenseData;
709 UINT8 SenseDataLength;
710 BOOLEAN NeedRetry;
711 UINTN Lun;
712
713 Status = EFI_SUCCESS;
714 NeedRetry = TRUE;
715 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
716
717 ZeroMem (&SenseData, sizeof (SenseData));
718 SenseDataLength = sizeof (SenseData);
719
720 //
721 // Check parameters
722 //
723 if (Buffer == NULL) {
724 return EFI_INVALID_PARAMETER;
725 }
726
727 if (BufferSize == 0) {
728 return EFI_SUCCESS;
729 }
730
731 if ((DeviceIndex == 0) || (DeviceIndex > UFS_PEIM_MAX_LUNS)) {
732 return EFI_INVALID_PARAMETER;
733 }
734
735 Lun = DeviceIndex - 1;
736 if ((Private->Luns.BitMask & (BIT0 << Lun)) == 0) {
737 return EFI_ACCESS_DENIED;
738 }
739
740 BlockSize = Private->Media[Lun].BlockSize;
741
742 if (BufferSize % BlockSize != 0) {
743 Status = EFI_BAD_BUFFER_SIZE;
744 }
745
746 if (StartLBA > Private->Media[Lun].LastBlock) {
747 Status = EFI_INVALID_PARAMETER;
748 }
749
750 NumberOfBlocks = BufferSize / BlockSize;
751
752 do {
753 Status = UfsPeimTestUnitReady (
754 Private,
755 Lun,
756 &SenseData,
757 &SenseDataLength
758 );
759 if (!EFI_ERROR (Status)) {
760 break;
761 }
762
763 if (SenseDataLength == 0) {
764 continue;
765 }
766
767 Status = UfsPeimParsingSenseKeys (&(Private->Media[Lun]), &SenseData, &NeedRetry);
768 if (EFI_ERROR (Status)) {
769 return EFI_DEVICE_ERROR;
770 }
771 } while (NeedRetry);
772
773 SenseDataLength = 0;
774 if (Private->Media[Lun].LastBlock < 0xfffffffful) {
775 Status = UfsPeimRead10 (
776 Private,
777 Lun,
778 (UINT32)StartLBA,
779 (UINT32)NumberOfBlocks,
780 Buffer,
781 (UINT32 *)&BufferSize,
782 NULL,
783 &SenseDataLength
784 );
785 } else {
786 Status = UfsPeimRead16 (
787 Private,
788 Lun,
789 (UINT32)StartLBA,
790 (UINT32)NumberOfBlocks,
791 Buffer,
792 (UINT32 *)&BufferSize,
793 NULL,
794 &SenseDataLength
795 );
796 }
797
798 return Status;
799}
800
821EFIAPI
823 IN EFI_PEI_SERVICES **PeiServices,
825 OUT UINTN *NumberBlockDevices
826 )
827{
828 //
829 // For Ufs device, it has up to 8 normal Luns plus some well-known Luns.
830 // At PEI phase, we will only expose normal Luns to user.
831 // For those disabled Lun, when user try to access it, the operation would fail.
832 //
833 *NumberBlockDevices = UFS_PEIM_MAX_LUNS;
834 return EFI_SUCCESS;
835}
836
879EFIAPI
881 IN EFI_PEI_SERVICES **PeiServices,
883 IN UINTN DeviceIndex,
885 )
886{
887 EFI_STATUS Status;
890 UINTN Lun;
891
892 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
893
895 PeiServices,
896 &Private->BlkIoPpi,
897 DeviceIndex,
898 &Media
899 );
900 if (EFI_ERROR (Status)) {
901 return Status;
902 }
903
904 Lun = DeviceIndex - 1;
905 CopyMem (MediaInfo, &(Private->Media[Lun]), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));
906 return EFI_SUCCESS;
907}
908
944EFIAPI
946 IN EFI_PEI_SERVICES **PeiServices,
948 IN UINTN DeviceIndex,
949 IN EFI_PEI_LBA StartLBA,
950 IN UINTN BufferSize,
951 OUT VOID *Buffer
952 )
953{
954 EFI_STATUS Status;
956
957 Status = EFI_SUCCESS;
958 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
959
960 Status = UfsBlockIoPeimReadBlocks (
961 PeiServices,
962 &Private->BlkIoPpi,
963 DeviceIndex,
964 StartLBA,
965 BufferSize,
966 Buffer
967 );
968 return Status;
969}
970
983EFIAPI
985 IN EFI_PEI_SERVICES **PeiServices,
986 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
987 IN VOID *Ppi
988 )
989{
991
992 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);
993
994 if ((Private->Pool != NULL) && (Private->Pool->Head != NULL)) {
995 UfsPeimFreeMemPool (Private->Pool);
996 }
997
998 if (Private->UtpTmrlBase != NULL) {
1000 EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)),
1001 Private->UtpTmrlBase,
1002 Private->TmrlMapping
1003 );
1004 }
1005
1006 if (Private->UtpTrlBase != NULL) {
1008 EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TRD)),
1009 Private->UtpTrlBase,
1010 Private->TrlMapping
1011 );
1012 }
1013
1014 UfsControllerStop (Private);
1015
1016 return EFI_SUCCESS;
1017}
1018
1032 )
1033{
1034 EFI_STATUS Status;
1035 UINT8 DeviceInitStatus;
1036 UINT32 Timeout;
1037
1038 DeviceInitStatus = 0xFF;
1039 Timeout = PcdGet32 (PcdUfsInitialCompletionTimeout);
1040
1041 //
1042 // The host enables the device initialization completion by setting fDeviceInit flag.
1043 //
1044 Status = UfsSetFlag (Private, UfsFlagDevInit);
1045 if (EFI_ERROR (Status)) {
1046 return Status;
1047 }
1048
1049 do {
1050 Status = UfsReadFlag (Private, UfsFlagDevInit, &DeviceInitStatus);
1051 if (EFI_ERROR (Status)) {
1052 return Status;
1053 }
1054
1055 MicroSecondDelay (1);
1056 Timeout--;
1057 } while (DeviceInitStatus != 0 && Timeout != 0);
1058
1059 if (Timeout == 0) {
1060 DEBUG ((DEBUG_ERROR, "%a: DeviceInitStatus = %x EFI_TIMEOUT \n", __func__, DeviceInitStatus));
1061 return EFI_TIMEOUT;
1062 } else {
1063 DEBUG ((DEBUG_INFO, "%a: Timeout left = %x EFI_SUCCESS \n", __func__, Timeout));
1064 return EFI_SUCCESS;
1065 }
1066}
1067
1079EFIAPI
1081 IN EFI_PEI_FILE_HANDLE FileHandle,
1082 IN CONST EFI_PEI_SERVICES **PeiServices
1083 )
1084{
1085 EFI_STATUS Status;
1086 UFS_PEIM_HC_PRIVATE_DATA *Private;
1088 UINT32 Index;
1089 UINTN MmioBase;
1090 UINT8 Controller;
1091 UFS_UNIT_DESC UnitDescriptor;
1092 EDKII_UFS_HC_PLATFORM_PPI *UfsHcPlatformPpi = NULL;
1093 UFS_DEV_DESC DeviceDescriptor;
1094 UINT8 RefClkAttr;
1095 EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE Attributes;
1096
1097 //
1098 // Shadow this PEIM to run from memory
1099 //
1100 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
1101 return EFI_SUCCESS;
1102 }
1103
1104 //
1105 // locate ufs host controller PPI
1106 //
1107 Status = PeiServicesLocatePpi (
1108 &gEdkiiPeiUfsHostControllerPpiGuid,
1109 0,
1110 NULL,
1111 (VOID **)&UfsHcPpi
1112 );
1113 if (EFI_ERROR (Status)) {
1114 return EFI_DEVICE_ERROR;
1115 }
1116
1117 //
1118 // Locate ufs host controller platform PPI
1119 //
1120 Status = PeiServicesLocatePpi (
1121 &gEdkiiUfsHcPlatformPpiGuid,
1122 0,
1123 NULL,
1124 (VOID **)&UfsHcPlatformPpi
1125 );
1126 if (EFI_ERROR (Status)) {
1127 DEBUG ((DEBUG_ERROR, "LocatePpi gEdkiiUfsHcPlatformPpiGuid Status :%r\n", Status));
1128 }
1129
1130 IoMmuInit ();
1131
1132 Controller = 0;
1133 MmioBase = 0;
1134 while (TRUE) {
1135 Status = UfsHcPpi->GetUfsHcMmioBar (UfsHcPpi, Controller, &MmioBase);
1136 //
1137 // When status is error, meant no controller is found
1138 //
1139 if (EFI_ERROR (Status)) {
1140 break;
1141 }
1142
1143 Private = AllocateCopyPool (sizeof (UFS_PEIM_HC_PRIVATE_DATA), &gUfsHcPeimTemplate);
1144 if (Private == NULL) {
1145 Status = EFI_OUT_OF_RESOURCES;
1146 break;
1147 }
1148
1149 Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
1150 Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;
1151 Private->UfsHcBase = MmioBase;
1152
1153 //
1154 // Initialize the memory pool which will be used in all transactions.
1155 //
1156 Status = UfsPeimInitMemPool (Private);
1157 if (EFI_ERROR (Status)) {
1158 Status = EFI_OUT_OF_RESOURCES;
1159 break;
1160 }
1161
1162 //
1163 // Initialize UFS Host Controller H/W.
1164 //
1165 Status = UfsControllerInit (UfsHcPlatformPpi, Private);
1166 if (EFI_ERROR (Status)) {
1167 DEBUG ((DEBUG_ERROR, "UfsDevicePei: Host Controller Initialization Error, Status = %r\n", Status));
1168 Controller++;
1169 continue;
1170 }
1171
1172 //
1173 // UFS 2.0 spec Section 13.1.3.3:
1174 // At the end of the UFS Interconnect Layer initialization on both host and device side,
1175 // the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.
1176 //
1177 Status = UfsExecNopCmds (Private);
1178 if (EFI_ERROR (Status)) {
1179 DEBUG ((DEBUG_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));
1180 Controller++;
1181 continue;
1182 }
1183
1184 //
1185 // Check the UFS device is initialized completed.
1186 //
1187 Status = UfsFinishDeviceInitialization (Private);
1188 if (EFI_ERROR (Status)) {
1189 DEBUG ((DEBUG_ERROR, "Device failed to finish initialization, Status = %r\n", Status));
1190 Controller++;
1191 continue;
1192 }
1193
1194 if ((UfsHcPlatformPpi != NULL) &&
1195 ((UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq19p2Mhz) ||
1196 (UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq26Mhz) ||
1197 (UfsHcPlatformPpi->RefClkFreq == EdkiiUfsCardRefClkFreq38p4Mhz)))
1198 {
1199 RefClkAttr = UfsAttrRefClkFreq;
1200 Attributes = EdkiiUfsCardRefClkFreqObsolete;
1201
1202 Status = UfsRwAttributes (Private, TRUE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
1203 DEBUG ((DEBUG_INFO, "UfsRwAttributes #1 Status = %r \n", Status));
1204 if (!EFI_ERROR (Status)) {
1205 if (Attributes != UfsHcPlatformPpi->RefClkFreq) {
1206 Attributes = UfsHcPlatformPpi->RefClkFreq;
1207 DEBUG (
1208 (DEBUG_INFO,
1209 "Setting bRefClkFreq attribute(%x) to %x\n 0 -> 19.2 Mhz\n 1 -> 26 Mhz\n 2 -> 38.4 Mhz\n 3 -> Obsolete\n",
1210 RefClkAttr,
1211 Attributes)
1212 );
1213 Status = UfsRwAttributes (Private, FALSE, RefClkAttr, 0, 0, (UINT32 *)&Attributes);
1214 DEBUG ((DEBUG_INFO, "UfsRwAttributes #2 Status = %r \n", Status));
1215 if (EFI_ERROR (Status)) {
1216 DEBUG (
1217 (DEBUG_ERROR,
1218 "Failed to Change Reference Clock Attribute to, Status = %r \n",
1219 Status)
1220 );
1221 }
1222 }
1223 } else {
1224 DEBUG (
1225 (DEBUG_ERROR,
1226 "Failed to Read Reference Clock Attribute, Status = %r \n",
1227 Status)
1228 );
1229 }
1230 }
1231
1232 if ((UfsHcPlatformPpi != NULL) && (UfsHcPlatformPpi->Callback != NULL)) {
1233 Status = UfsHcPlatformPpi->Callback (&Private->UfsHcBase, EdkiiUfsHcPostLinkStartup);
1234 if (EFI_ERROR (Status)) {
1235 DEBUG ((DEBUG_ERROR, "Failure from platform driver during EdkiiUfsHcPostLinkStartup, Status = %r\n", Status));
1236 Controller++;
1237 continue;
1238 }
1239
1240 //
1241 // Check if 8 common luns are active and set corresponding bit mask.
1242 //
1243 for (Index = 0; Index < UFS_PEIM_MAX_LUNS; Index++) {
1244 Status = UfsRwDeviceDesc (Private, TRUE, UfsUnitDesc, (UINT8)Index, 0, &UnitDescriptor, sizeof (UFS_UNIT_DESC));
1245 if (EFI_ERROR (Status)) {
1246 DEBUG ((DEBUG_ERROR, "Fail to read UFS Unit Descriptor, Index = %X, Status = %r\n", Index, Status));
1247 continue;
1248 }
1249
1250 if (UnitDescriptor.LunEn == 0x1) {
1251 DEBUG ((DEBUG_INFO, "Ufs %d Lun %d is enabled\n", Controller, Index));
1252 Private->Luns.BitMask |= (BIT0 << Index);
1253 }
1254 }
1255
1256 //
1257 // Get Ufs Device's Lun Info by reading Configuration Descriptor
1258 //
1259 Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &DeviceDescriptor, sizeof (UFS_DEV_DESC));
1260 if (EFI_ERROR (Status)) {
1261 DEBUG ((DEBUG_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));
1262 Controller++;
1263 continue;
1264 }
1265
1266 if (DeviceDescriptor.SecurityLun == 0x1) {
1267 DEBUG ((DEBUG_INFO, "UFS WLUN RPMB is supported\n"));
1268 Private->Luns.BitMask |= BIT11;
1269 }
1270
1271 PeiServicesInstallPpi (&Private->BlkIoPpiList);
1272 PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);
1273 Controller++;
1274 }
1275 }
1276
1277 return EFI_SUCCESS;
1278}
UINT64 UINTN
EFI_STATUS IoMmuFreeBuffer(IN UINTN Pages, IN VOID *HostAddress, IN VOID *Mapping)
Definition: DmaMem.c:251
UINTN EFIAPI MicroSecondDelay(IN UINTN MicroSeconds)
UINT16 EFIAPI SwapBytes16(IN UINT16 Value)
Definition: SwapBytes16.c:25
UINT32 EFIAPI SwapBytes32(IN UINT32 Value)
Definition: SwapBytes32.c:25
UINT32 EFIAPI WriteUnaligned32(OUT UINT32 *Buffer, IN UINT32 Value)
Definition: Unaligned.c:177
UINT16 EFIAPI WriteUnaligned16(OUT UINT16 *Buffer, IN UINT16 Value)
Definition: Unaligned.c:61
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition: LShiftU64.c:28
UINT64 EFIAPI SwapBytes64(IN UINT64 Value)
Definition: SwapBytes64.c:25
UINT64 EFIAPI WriteUnaligned64(OUT UINT64 *Buffer, IN UINT64 Value)
Definition: Unaligned.c:236
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define MSG_UFS_DP
Definition: DevicePath.h:891
VOID *EFIAPI AllocateCopyPool(IN UINTN AllocationSize, IN CONST VOID *Buffer)
EFI_STATUS EFIAPI PeiServicesLocatePpi(IN CONST EFI_GUID *Guid, IN UINTN Instance, IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, IN OUT VOID **Ppi)
EFI_STATUS EFIAPI PeiServicesNotifyPpi(IN CONST EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList)
EFI_STATUS EFIAPI PeiServicesInstallPpi(IN CONST EFI_PEI_PPI_DESCRIPTOR *PpiList)
EFI_STATUS EFIAPI PeiServicesRegisterForShadow(IN EFI_PEI_FILE_HANDLE FileHandle)
#define NULL
Definition: Base.h:319
#define CONST
Definition: Base.h:259
#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 DEBUG(Expression)
Definition: DebugLib.h:434
@ UfsDevice
The recovery device is a Universal Flash Storage device.
Definition: BlockIo.h:53
UINT64 EFI_PEI_LBA
Definition: BlockIo.h:41
#define PcdGet32(TokenName)
Definition: PcdLib.h:362
VOID IoMmuInit(OUT EDKII_IOMMU_PPI **IoMmu)
Definition: DmaMem.c:238
VOID * EFI_PEI_FILE_HANDLE
Definition: PiPeiCis.h:26
#define EFI_SCSI_ASC_RESET
Power On Reset or Bus Reset occurred.
Definition: Scsi.h:420
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_SIZE_TO_PAGES(Size)
Definition: UefiBaseType.h:200
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_STATUS EFIAPI UfsBlockIoPeimReadBlocks(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, IN UINTN DeviceIndex, IN EFI_PEI_LBA StartLBA, IN UINTN BufferSize, OUT VOID *Buffer)
EFI_STATUS UfsFinishDeviceInitialization(IN UFS_PEIM_HC_PRIVATE_DATA *Private)
EFI_STATUS UfsPeimReadCapacity(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINTN Lun, OUT VOID *DataBuffer, OUT UINT32 *DataLength, OUT VOID *SenseData OPTIONAL, OUT UINT8 *SenseDataLength)
EFI_STATUS EFIAPI UfsBlockIoPeimReadBlocks2(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, IN UINTN DeviceIndex, IN EFI_PEI_LBA StartLBA, IN UINTN BufferSize, OUT VOID *Buffer)
EFI_STATUS EFIAPI UfsEndOfPei(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, IN VOID *Ppi)
EFI_STATUS UfsPeimReadCapacity16(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINTN Lun, OUT VOID *DataBuffer, OUT UINT32 *DataLength, OUT VOID *SenseData OPTIONAL, OUT UINT8 *SenseDataLength)
EFI_STATUS UfsPeimRead10(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINTN Lun, IN UINTN StartLba, IN UINT32 SectorNum, OUT VOID *DataBuffer, OUT UINT32 *DataLength, OUT VOID *SenseData OPTIONAL, OUT UINT8 *SenseDataLength)
EFI_STATUS UfsPeimTestUnitReady(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINTN Lun, OUT VOID *SenseData OPTIONAL, OUT UINT8 *SenseDataLength)
EFI_STATUS EFIAPI InitializeUfsBlockIoPeim(IN EFI_PEI_FILE_HANDLE FileHandle, IN CONST EFI_PEI_SERVICES **PeiServices)
EFI_STATUS EFIAPI UfsBlockIoPeimGetMediaInfo(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, IN UINTN DeviceIndex, OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo)
EFI_STATUS EFIAPI UfsBlockIoPeimGetDeviceNo2(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, OUT UINTN *NumberBlockDevices)
EFI_STATUS EFIAPI UfsBlockIoPeimGetMediaInfo2(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This, IN UINTN DeviceIndex, OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo)
EFI_STATUS UfsPeimRead16(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINTN Lun, IN UINTN StartLba, IN UINT32 SectorNum, OUT VOID *DataBuffer, OUT UINT32 *DataLength, OUT VOID *SenseData OPTIONAL, OUT UINT8 *SenseDataLength)
EFI_STATUS UfsPeimParsingSenseKeys(IN EFI_PEI_BLOCK_IO2_MEDIA *Media, IN EFI_SCSI_SENSE_DATA *SenseData, OUT BOOLEAN *NeedRetry)
EFI_STATUS EFIAPI UfsBlockIoPeimGetDeviceNo(IN EFI_PEI_SERVICES **PeiServices, IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, OUT UINTN *NumberBlockDevices)
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 UfsPeimFreeMemPool(IN UFS_PEIM_MEM_POOL *Pool)
Definition: UfsHcMem.c:264
EFI_STATUS UfsReadFlag(IN UFS_PEIM_HC_PRIVATE_DATA *Private, IN UINT8 FlagId, OUT UINT8 *Value)
Definition: UfsHci.c:1144
EFI_STATUS UfsPeimInitMemPool(IN UFS_PEIM_HC_PRIVATE_DATA *Private)
Definition: UfsHcMem.c:224
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
EDKII_UFS_CARD_REF_CLK_FREQ_ATTRIBUTE RefClkFreq
EDKII_UFS_HC_PLATFORM_PEI_CALLBACK Callback
EFI_PEI_LBA LastBlock
Definition: BlockIo2.h:64