]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.c
MdeModulePkg: Removing ipf which is no longer supported from edk2.
[mirror_edk2.git] / MdeModulePkg / Bus / Ufs / UfsBlockIoPei / UfsBlockIoPei.c
CommitLineData
0591696e
FT
1/** @file\r
2\r
d1102dba 3 Copyright (c) 2014 - 2018, Intel Corporation. All rights reserved.<BR>\r
0591696e
FT
4 This program and the accompanying materials\r
5 are licensed and made available under the terms and conditions of the BSD License\r
6 which accompanies this distribution. The full text of the license may be found at\r
7 http://opensource.org/licenses/bsd-license.php\r
8\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12**/\r
13\r
14#include "UfsBlockIoPei.h"\r
15\r
16//\r
17// Template for UFS HC Peim Private Data.\r
18//\r
19UFS_PEIM_HC_PRIVATE_DATA gUfsHcPeimTemplate = {\r
20 UFS_PEIM_HC_SIG, // Signature\r
21 NULL, // Controller\r
22 NULL, // Pool\r
23 { // BlkIoPpi\r
24 UfsBlockIoPeimGetDeviceNo,\r
25 UfsBlockIoPeimGetMediaInfo,\r
26 UfsBlockIoPeimReadBlocks\r
27 },\r
9d02f824
FT
28 { // BlkIo2Ppi\r
29 EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,\r
30 UfsBlockIoPeimGetDeviceNo2,\r
31 UfsBlockIoPeimGetMediaInfo2,\r
32 UfsBlockIoPeimReadBlocks2\r
33 },\r
0591696e 34 { // BlkIoPpiList\r
9d02f824 35 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
0591696e
FT
36 &gEfiPeiVirtualBlockIoPpiGuid,\r
37 NULL\r
38 },\r
9d02f824
FT
39 { // BlkIo2PpiList\r
40 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
41 &gEfiPeiVirtualBlockIo2PpiGuid,\r
42 NULL\r
43 },\r
0591696e
FT
44 { // Media\r
45 {\r
9d02f824
FT
46 MSG_UFS_DP,\r
47 FALSE,\r
0591696e 48 TRUE,\r
9d02f824
FT
49 FALSE,\r
50 0x1000,\r
51 0\r
0591696e
FT
52 },\r
53 {\r
9d02f824
FT
54 MSG_UFS_DP,\r
55 FALSE,\r
0591696e 56 TRUE,\r
9d02f824
FT
57 FALSE,\r
58 0x1000,\r
59 0\r
0591696e
FT
60 },\r
61 {\r
9d02f824
FT
62 MSG_UFS_DP,\r
63 FALSE,\r
0591696e 64 TRUE,\r
9d02f824
FT
65 FALSE,\r
66 0x1000,\r
67 0\r
0591696e
FT
68 },\r
69 {\r
9d02f824
FT
70 MSG_UFS_DP,\r
71 FALSE,\r
0591696e 72 TRUE,\r
9d02f824
FT
73 FALSE,\r
74 0x1000,\r
75 0\r
0591696e
FT
76 },\r
77 {\r
9d02f824
FT
78 MSG_UFS_DP,\r
79 FALSE,\r
0591696e 80 TRUE,\r
9d02f824
FT
81 FALSE,\r
82 0x1000,\r
83 0\r
0591696e
FT
84 },\r
85 {\r
9d02f824
FT
86 MSG_UFS_DP,\r
87 FALSE,\r
0591696e 88 TRUE,\r
9d02f824
FT
89 FALSE,\r
90 0x1000,\r
91 0\r
0591696e
FT
92 },\r
93 {\r
9d02f824
FT
94 MSG_UFS_DP,\r
95 FALSE,\r
0591696e 96 TRUE,\r
9d02f824
FT
97 FALSE,\r
98 0x1000,\r
99 0\r
0591696e
FT
100 },\r
101 {\r
9d02f824
FT
102 MSG_UFS_DP,\r
103 FALSE,\r
0591696e 104 TRUE,\r
9d02f824
FT
105 FALSE,\r
106 0x1000,\r
107 0\r
0591696e
FT
108 }\r
109 },\r
44a0857e
HW
110 { // EndOfPeiNotifyList\r
111 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
112 &gEfiEndOfPeiSignalPpiGuid,\r
113 UfsEndOfPei\r
114 },\r
0591696e
FT
115 0, // UfsHcBase\r
116 0, // Capabilities\r
117 0, // TaskTag\r
118 0, // UtpTrlBase\r
119 0, // Nutrs\r
44a0857e 120 NULL, // TrlMapping\r
0591696e
FT
121 0, // UtpTmrlBase\r
122 0, // Nutmrs\r
44a0857e 123 NULL, // TmrlMapping\r
0591696e
FT
124 { // Luns\r
125 {\r
126 UFS_LUN_0, // Ufs Common Lun 0\r
127 UFS_LUN_1, // Ufs Common Lun 1\r
128 UFS_LUN_2, // Ufs Common Lun 2\r
129 UFS_LUN_3, // Ufs Common Lun 3\r
130 UFS_LUN_4, // Ufs Common Lun 4\r
131 UFS_LUN_5, // Ufs Common Lun 5\r
132 UFS_LUN_6, // Ufs Common Lun 6\r
133 UFS_LUN_7, // Ufs Common Lun 7\r
134 },\r
135 0x0000, // By default exposing all Luns.\r
136 0x0\r
137 }\r
138};\r
139\r
0591696e 140\r
0591696e
FT
141\r
142/**\r
143 Execute TEST UNITY READY SCSI command on a specific UFS device.\r
144\r
145 @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.\r
146 @param[in] Lun The lun on which the SCSI cmd executed.\r
147 @param[out] SenseData A pointer to output sense data.\r
148 @param[out] SenseDataLength The length of output sense data.\r
149\r
150 @retval EFI_SUCCESS The command executed successfully.\r
151 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
152 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
153\r
154**/\r
155EFI_STATUS\r
156UfsPeimTestUnitReady (\r
157 IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
d1102dba 158 IN UINTN Lun,\r
0591696e
FT
159 OUT VOID *SenseData, OPTIONAL\r
160 OUT UINT8 *SenseDataLength\r
d1102dba 161 )\r
0591696e
FT
162{\r
163 UFS_SCSI_REQUEST_PACKET Packet;\r
164 UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];\r
165 EFI_STATUS Status;\r
166\r
167 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));\r
168 ZeroMem (Cdb, sizeof (Cdb));\r
169\r
170 Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;\r
171\r
172 Packet.Timeout = UFS_TIMEOUT;\r
173 Packet.Cdb = Cdb;\r
174 Packet.CdbLength = sizeof (Cdb);\r
175 Packet.DataDirection = UfsNoData;\r
176 Packet.SenseData = SenseData;\r
177 Packet.SenseDataLength = *SenseDataLength;\r
178\r
179 Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);\r
180\r
181 if (*SenseDataLength != 0) {\r
182 *SenseDataLength = Packet.SenseDataLength;\r
183 }\r
184\r
185 return Status;\r
186}\r
187\r
0591696e 188\r
0591696e
FT
189\r
190/**\r
191 Execute READ CAPACITY(10) SCSI command on a specific UFS device.\r
192\r
193 @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.\r
194 @param[in] Lun The lun on which the SCSI cmd executed.\r
195 @param[out] DataBuffer A pointer to READ_CAPACITY data buffer.\r
196 @param[out] DataLength The length of output READ_CAPACITY data.\r
197 @param[out] SenseData A pointer to output sense data.\r
198 @param[out] SenseDataLength The length of output sense data.\r
199\r
200 @retval EFI_SUCCESS The command executed successfully.\r
201 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
202 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
203\r
204**/\r
205EFI_STATUS\r
206UfsPeimReadCapacity (\r
207 IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
208 IN UINTN Lun,\r
209 OUT VOID *DataBuffer,\r
210 OUT UINT32 *DataLength,\r
211 OUT VOID *SenseData, OPTIONAL\r
212 OUT UINT8 *SenseDataLength\r
d1102dba 213 )\r
0591696e
FT
214{\r
215 UFS_SCSI_REQUEST_PACKET Packet;\r
216 UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];\r
217 EFI_STATUS Status;\r
218\r
219 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));\r
220 ZeroMem (Cdb, sizeof (Cdb));\r
221\r
222 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;\r
223\r
224 Packet.Timeout = UFS_TIMEOUT;\r
225 Packet.Cdb = Cdb;\r
226 Packet.CdbLength = sizeof (Cdb);\r
227 Packet.InDataBuffer = DataBuffer;\r
228 Packet.InTransferLength = *DataLength;\r
229 Packet.DataDirection = UfsDataIn;\r
230 Packet.SenseData = SenseData;\r
231 Packet.SenseDataLength = *SenseDataLength;\r
232\r
233 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);\r
234\r
235 if (*SenseDataLength != 0) {\r
236 *SenseDataLength = Packet.SenseDataLength;\r
237 }\r
238\r
239 if (!EFI_ERROR (Status)) {\r
240 *DataLength = Packet.InTransferLength;\r
241 }\r
242\r
243 return Status;\r
244}\r
245\r
246/**\r
247 Execute READ CAPACITY(16) SCSI command on a specific UFS device.\r
248\r
249 @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.\r
250 @param[in] Lun The lun on which the SCSI cmd executed.\r
251 @param[out] DataBuffer A pointer to READ_CAPACITY data buffer.\r
252 @param[out] DataLength The length of output READ_CAPACITY data.\r
253 @param[out] SenseData A pointer to output sense data.\r
254 @param[out] SenseDataLength The length of output sense data.\r
255\r
256 @retval EFI_SUCCESS The command executed successfully.\r
257 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
258 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
259\r
260**/\r
261EFI_STATUS\r
262UfsPeimReadCapacity16 (\r
263 IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
264 IN UINTN Lun,\r
265 OUT VOID *DataBuffer,\r
266 OUT UINT32 *DataLength,\r
267 OUT VOID *SenseData, OPTIONAL\r
268 OUT UINT8 *SenseDataLength\r
d1102dba 269 )\r
0591696e
FT
270{\r
271 UFS_SCSI_REQUEST_PACKET Packet;\r
272 UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];\r
273 EFI_STATUS Status;\r
274\r
275 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));\r
276 ZeroMem (Cdb, sizeof (Cdb));\r
277\r
278 Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;\r
279 Cdb[1] = 0x10; // Service Action should be 0x10 for UFS device.\r
280 Cdb[13] = 0x20; // The maximum number of bytes for returned data.\r
281\r
282 Packet.Timeout = UFS_TIMEOUT;\r
283 Packet.Cdb = Cdb;\r
284 Packet.CdbLength = sizeof (Cdb);\r
285 Packet.InDataBuffer = DataBuffer;\r
286 Packet.InTransferLength = *DataLength;\r
287 Packet.DataDirection = UfsDataIn;\r
288 Packet.SenseData = SenseData;\r
289 Packet.SenseDataLength = *SenseDataLength;\r
290\r
291 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);\r
292\r
293 if (*SenseDataLength != 0) {\r
294 *SenseDataLength = Packet.SenseDataLength;\r
295 }\r
296\r
297 if (!EFI_ERROR (Status)) {\r
298 *DataLength = Packet.InTransferLength;\r
299 }\r
300\r
301 return Status;\r
302}\r
303\r
304/**\r
305 Execute READ (10) SCSI command on a specific UFS device.\r
306\r
307 @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.\r
308 @param[in] Lun The lun on which the SCSI cmd executed.\r
309 @param[in] StartLba The start LBA.\r
310 @param[in] SectorNum The sector number to be read.\r
311 @param[out] DataBuffer A pointer to data buffer.\r
312 @param[out] DataLength The length of output data.\r
313 @param[out] SenseData A pointer to output sense data.\r
314 @param[out] SenseDataLength The length of output sense data.\r
315\r
316 @retval EFI_SUCCESS The command executed successfully.\r
317 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
318 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
319\r
320**/\r
321EFI_STATUS\r
322UfsPeimRead10 (\r
323 IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
324 IN UINTN Lun,\r
325 IN UINTN StartLba,\r
326 IN UINT32 SectorNum,\r
327 OUT VOID *DataBuffer,\r
328 OUT UINT32 *DataLength,\r
329 OUT VOID *SenseData, OPTIONAL\r
330 OUT UINT8 *SenseDataLength\r
d1102dba 331 )\r
0591696e
FT
332{\r
333 UFS_SCSI_REQUEST_PACKET Packet;\r
334 UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];\r
335 EFI_STATUS Status;\r
336\r
337 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));\r
338 ZeroMem (Cdb, sizeof (Cdb));\r
339\r
340 Cdb[0] = EFI_SCSI_OP_READ10;\r
341 WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 ((UINT32) StartLba));\r
342 WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorNum));\r
343\r
344 Packet.Timeout = UFS_TIMEOUT;\r
345 Packet.Cdb = Cdb;\r
346 Packet.CdbLength = sizeof (Cdb);\r
347 Packet.InDataBuffer = DataBuffer;\r
348 Packet.InTransferLength = *DataLength;\r
349 Packet.DataDirection = UfsDataIn;\r
350 Packet.SenseData = SenseData;\r
351 Packet.SenseDataLength = *SenseDataLength;\r
352\r
353 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);\r
354\r
355 if (*SenseDataLength != 0) {\r
356 *SenseDataLength = Packet.SenseDataLength;\r
357 }\r
358\r
359 if (!EFI_ERROR (Status)) {\r
360 *DataLength = Packet.InTransferLength;\r
361 }\r
362\r
363 return Status;\r
364}\r
365\r
366/**\r
367 Execute READ (16) SCSI command on a specific UFS device.\r
368\r
369 @param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.\r
370 @param[in] Lun The lun on which the SCSI cmd executed.\r
371 @param[in] StartLba The start LBA.\r
372 @param[in] SectorNum The sector number to be read.\r
373 @param[out] DataBuffer A pointer to data buffer.\r
374 @param[out] DataLength The length of output data.\r
375 @param[out] SenseData A pointer to output sense data.\r
376 @param[out] SenseDataLength The length of output sense data.\r
377\r
378 @retval EFI_SUCCESS The command executed successfully.\r
379 @retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.\r
380 @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.\r
381\r
382**/\r
383EFI_STATUS\r
384UfsPeimRead16 (\r
385 IN UFS_PEIM_HC_PRIVATE_DATA *Private,\r
386 IN UINTN Lun,\r
387 IN UINTN StartLba,\r
388 IN UINT32 SectorNum,\r
389 OUT VOID *DataBuffer,\r
390 OUT UINT32 *DataLength,\r
391 OUT VOID *SenseData, OPTIONAL\r
392 OUT UINT8 *SenseDataLength\r
d1102dba 393 )\r
0591696e
FT
394{\r
395 UFS_SCSI_REQUEST_PACKET Packet;\r
396 UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];\r
397 EFI_STATUS Status;\r
398\r
399 ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));\r
400 ZeroMem (Cdb, sizeof (Cdb));\r
401\r
402 Cdb[0] = EFI_SCSI_OP_READ16;\r
403 WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));\r
404 WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorNum));\r
405\r
406 Packet.Timeout = UFS_TIMEOUT;\r
407 Packet.Cdb = Cdb;\r
408 Packet.CdbLength = sizeof (Cdb);\r
409 Packet.InDataBuffer = DataBuffer;\r
410 Packet.InTransferLength = *DataLength;\r
411 Packet.DataDirection = UfsDataIn;\r
412 Packet.SenseData = SenseData;\r
413 Packet.SenseDataLength = *SenseDataLength;\r
414\r
415 Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);\r
416\r
417 if (*SenseDataLength != 0) {\r
418 *SenseDataLength = Packet.SenseDataLength;\r
419 }\r
420\r
421 if (!EFI_ERROR (Status)) {\r
422 *DataLength = Packet.InTransferLength;\r
423 }\r
424\r
425 return Status;\r
426}\r
427\r
428/**\r
429 Parsing Sense Keys from sense data.\r
430\r
431 @param Media The pointer of EFI_PEI_BLOCK_IO_MEDIA\r
432 @param SenseData The pointer of EFI_SCSI_SENSE_DATA\r
433 @param NeedRetry The pointer of action which indicates what is need to retry\r
434\r
435 @retval EFI_DEVICE_ERROR Indicates that error occurs\r
436 @retval EFI_SUCCESS Successfully to complete the parsing\r
437\r
438**/\r
439EFI_STATUS\r
440UfsPeimParsingSenseKeys (\r
9d02f824 441 IN EFI_PEI_BLOCK_IO2_MEDIA *Media,\r
0591696e
FT
442 IN EFI_SCSI_SENSE_DATA *SenseData,\r
443 OUT BOOLEAN *NeedRetry\r
444 )\r
445{\r
446 if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&\r
447 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {\r
448 Media->MediaPresent = FALSE;\r
449 *NeedRetry = FALSE;\r
450 DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is No Media\n"));\r
451 return EFI_DEVICE_ERROR;\r
452 }\r
453\r
454 if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&\r
455 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {\r
456 *NeedRetry = TRUE;\r
457 DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is Media Change\n"));\r
458 return EFI_SUCCESS;\r
459 }\r
460\r
461 if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&\r
462 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {\r
463 *NeedRetry = TRUE;\r
464 DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));\r
465 return EFI_SUCCESS;\r
466 }\r
467\r
468 if ((SenseData->Sense_Key == EFI_SCSI_SK_MEDIUM_ERROR) ||\r
469 ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&\r
470 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN))) {\r
471 *NeedRetry = FALSE;\r
472 DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Media Error\n"));\r
473 return EFI_DEVICE_ERROR;\r
474 }\r
475\r
476 if (SenseData->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {\r
477 *NeedRetry = FALSE;\r
478 DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Hardware Error\n"));\r
479 return EFI_DEVICE_ERROR;\r
480 }\r
481\r
482 if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&\r
483 (SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NOT_READY) &&\r
484 (SenseData->Addnl_Sense_Code_Qualifier == EFI_SCSI_ASCQ_IN_PROGRESS)) {\r
485 *NeedRetry = TRUE;\r
486 DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));\r
487 return EFI_SUCCESS;\r
488 }\r
489\r
490 *NeedRetry = FALSE;\r
491 DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Sense Key = 0x%x ASC = 0x%x!\n", SenseData->Sense_Key, SenseData->Addnl_Sense_Code));\r
492 return EFI_DEVICE_ERROR;\r
493}\r
494\r
495\r
496/**\r
497 Gets the count of block I/O devices that one specific block driver detects.\r
498\r
d1102dba 499 This function is used for getting the count of block I/O devices that one\r
0591696e 500 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
d1102dba
LG
501 of all the detected ATAPI devices it detects during the enumeration process.\r
502 To the PEI legacy floppy driver, it returns the number of all the legacy\r
503 devices it finds during its enumeration process. If no device is detected,\r
504 then the function will return zero.\r
505\r
506 @param[in] PeiServices General-purpose services that are available\r
0591696e 507 to every PEIM.\r
d1102dba 508 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI\r
0591696e
FT
509 instance.\r
510 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
511\r
512 @retval EFI_SUCCESS The operation performed successfully.\r
513\r
514**/\r
515EFI_STATUS\r
516EFIAPI\r
517UfsBlockIoPeimGetDeviceNo (\r
518 IN EFI_PEI_SERVICES **PeiServices,\r
519 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
520 OUT UINTN *NumberBlockDevices\r
521 )\r
522{\r
523 //\r
524 // For Ufs device, it has up to 8 normal Luns plus some well-known Luns.\r
525 // At PEI phase, we will only expose normal Luns to user.\r
526 // For those disabled Lun, when user try to access it, the operation would fail.\r
527 //\r
528 *NumberBlockDevices = UFS_PEIM_MAX_LUNS;\r
529 return EFI_SUCCESS;\r
530}\r
531\r
532/**\r
533 Gets a block device's media information.\r
534\r
d1102dba
LG
535 This function will provide the caller with the specified block device's media\r
536 information. If the media changes, calling this function will update the media\r
0591696e
FT
537 information accordingly.\r
538\r
539 @param[in] PeiServices General-purpose services that are available to every\r
540 PEIM\r
541 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
d1102dba
LG
542 @param[in] DeviceIndex Specifies the block device to which the function wants\r
543 to talk. Because the driver that implements Block I/O\r
544 PPIs will manage multiple block devices, the PPIs that\r
545 want to talk to a single device must specify the\r
0591696e 546 device index that was assigned during the enumeration\r
d1102dba 547 process. This index is a number from one to\r
0591696e 548 NumberBlockDevices.\r
d1102dba
LG
549 @param[out] MediaInfo The media information of the specified block media.\r
550 The caller is responsible for the ownership of this\r
0591696e
FT
551 data structure.\r
552\r
d1102dba
LG
553 @par Note:\r
554 The MediaInfo structure describes an enumeration of possible block device\r
555 types. This enumeration exists because no device paths are actually passed\r
556 across interfaces that describe the type or class of hardware that is publishing\r
0591696e 557 the block I/O interface. This enumeration will allow for policy decisions\r
d1102dba
LG
558 in the Recovery PEIM, such as "Try to recover from legacy floppy first,\r
559 LS-120 second, CD-ROM third." If there are multiple partitions abstracted\r
560 by a given device type, they should be reported in ascending order; this\r
561 order also applies to nested partitions, such as legacy MBR, where the\r
562 outermost partitions would have precedence in the reporting order. The\r
563 same logic applies to systems such as IDE that have precedence relationships\r
564 like "Master/Slave" or "Primary/Secondary". The master device should be\r
0591696e 565 reported first, the slave second.\r
d1102dba
LG
566\r
567 @retval EFI_SUCCESS Media information about the specified block device\r
0591696e 568 was obtained successfully.\r
d1102dba 569 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
0591696e
FT
570 error.\r
571\r
572**/\r
573EFI_STATUS\r
574EFIAPI\r
575UfsBlockIoPeimGetMediaInfo (\r
576 IN EFI_PEI_SERVICES **PeiServices,\r
577 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
578 IN UINTN DeviceIndex,\r
579 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
580 )\r
581{\r
582 EFI_STATUS Status;\r
583 UFS_PEIM_HC_PRIVATE_DATA *Private;\r
584 EFI_SCSI_SENSE_DATA SenseData;\r
585 UINT8 SenseDataLength;\r
586 EFI_SCSI_DISK_CAPACITY_DATA Capacity;\r
587 EFI_SCSI_DISK_CAPACITY_DATA16 Capacity16;\r
588 UINTN DataLength;\r
d1102dba 589 BOOLEAN NeedRetry;\r
0591696e
FT
590\r
591 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
592 NeedRetry = TRUE;\r
593\r
594 if (DeviceIndex >= UFS_PEIM_MAX_LUNS) {\r
595 return EFI_INVALID_PARAMETER;\r
596 }\r
597\r
598 if ((Private->Luns.BitMask & (BIT0 << DeviceIndex)) == 0) {\r
599 return EFI_ACCESS_DENIED;\r
600 }\r
601\r
602 ZeroMem (&SenseData, sizeof (SenseData));\r
603 ZeroMem (&Capacity, sizeof (Capacity));\r
604 ZeroMem (&Capacity16, sizeof (Capacity16));\r
605 SenseDataLength = sizeof (SenseData);\r
606 //\r
607 // First test unit ready\r
608 //\r
609 do {\r
610 Status = UfsPeimTestUnitReady (\r
611 Private,\r
612 DeviceIndex,\r
613 &SenseData,\r
614 &SenseDataLength\r
615 );\r
616 if (!EFI_ERROR (Status)) {\r
617 break;\r
618 }\r
d1102dba 619\r
0591696e
FT
620 if (SenseDataLength == 0) {\r
621 continue;\r
622 }\r
623\r
624 Status = UfsPeimParsingSenseKeys (&(Private->Media[DeviceIndex]), &SenseData, &NeedRetry);\r
625 if (EFI_ERROR (Status)) {\r
626 return EFI_DEVICE_ERROR;\r
627 }\r
628\r
629 } while (NeedRetry);\r
630\r
631 DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);\r
632 SenseDataLength = 0;\r
633 Status = UfsPeimReadCapacity (Private, DeviceIndex, &Capacity, (UINT32 *)&DataLength, NULL, &SenseDataLength);\r
634 if (EFI_ERROR (Status)) {\r
635 return EFI_DEVICE_ERROR;\r
636 }\r
637\r
638 if ((Capacity.LastLba3 == 0xff) && (Capacity.LastLba2 == 0xff) &&\r
639 (Capacity.LastLba1 == 0xff) && (Capacity.LastLba0 == 0xff)) {\r
640 DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA16);\r
641 SenseDataLength = 0;\r
642 Status = UfsPeimReadCapacity16 (Private, DeviceIndex, &Capacity16, (UINT32 *)&DataLength, NULL, &SenseDataLength);\r
643 if (EFI_ERROR (Status)) {\r
644 return EFI_DEVICE_ERROR;\r
645 }\r
da117dda 646 Private->Media[DeviceIndex].LastBlock = ((UINT32)Capacity16.LastLba3 << 24) | (Capacity16.LastLba2 << 16) | (Capacity16.LastLba1 << 8) | Capacity16.LastLba0;\r
faf0f16c 647 Private->Media[DeviceIndex].LastBlock |= LShiftU64 ((UINT64)Capacity16.LastLba7, 56) | LShiftU64((UINT64)Capacity16.LastLba6, 48) | LShiftU64 ((UINT64)Capacity16.LastLba5, 40) | LShiftU64 ((UINT64)Capacity16.LastLba4, 32);\r
9d02f824 648 Private->Media[DeviceIndex].BlockSize = (Capacity16.BlockSize3 << 24) | (Capacity16.BlockSize2 << 16) | (Capacity16.BlockSize1 << 8) | Capacity16.BlockSize0;\r
0591696e 649 } else {\r
da117dda 650 Private->Media[DeviceIndex].LastBlock = ((UINT32)Capacity.LastLba3 << 24) | (Capacity.LastLba2 << 16) | (Capacity.LastLba1 << 8) | Capacity.LastLba0;\r
9d02f824 651 Private->Media[DeviceIndex].BlockSize = (Capacity.BlockSize3 << 24) | (Capacity.BlockSize2 << 16) | (Capacity.BlockSize1 << 8) | Capacity.BlockSize0;\r
0591696e
FT
652 }\r
653\r
654 MediaInfo->DeviceType = UfsDevice;\r
9d02f824
FT
655 MediaInfo->MediaPresent = Private->Media[DeviceIndex].MediaPresent;\r
656 MediaInfo->LastBlock = (UINTN)Private->Media[DeviceIndex].LastBlock;\r
657 MediaInfo->BlockSize = Private->Media[DeviceIndex].BlockSize;\r
0591696e
FT
658\r
659 return EFI_SUCCESS;\r
660}\r
661\r
662/**\r
663 Reads the requested number of blocks from the specified block device.\r
664\r
d1102dba 665 The function reads the requested number of blocks from the device. All the\r
0591696e
FT
666 blocks are read, or an error is returned. If there is no media in the device,\r
667 the function returns EFI_NO_MEDIA.\r
668\r
d1102dba 669 @param[in] PeiServices General-purpose services that are available to\r
0591696e
FT
670 every PEIM.\r
671 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
d1102dba
LG
672 @param[in] DeviceIndex Specifies the block device to which the function wants\r
673 to talk. Because the driver that implements Block I/O\r
674 PPIs will manage multiple block devices, PPIs that\r
675 want to talk to a single device must specify the device\r
676 index that was assigned during the enumeration process.\r
0591696e
FT
677 This index is a number from one to NumberBlockDevices.\r
678 @param[in] StartLBA The starting logical block address (LBA) to read from\r
679 on the device\r
680 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
681 a multiple of the intrinsic block size of the device.\r
682 @param[out] Buffer A pointer to the destination buffer for the data.\r
d1102dba 683 The caller is responsible for the ownership of the\r
0591696e 684 buffer.\r
d1102dba 685\r
0591696e 686 @retval EFI_SUCCESS The data was read correctly from the device.\r
d1102dba 687 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
0591696e 688 to perform the read operation.\r
d1102dba 689 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
0591696e
FT
690 valid, or the buffer is not properly aligned.\r
691 @retval EFI_NO_MEDIA There is no media in the device.\r
692 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
693 the intrinsic block size of the device.\r
694\r
695**/\r
696EFI_STATUS\r
697EFIAPI\r
698UfsBlockIoPeimReadBlocks (\r
699 IN EFI_PEI_SERVICES **PeiServices,\r
700 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
701 IN UINTN DeviceIndex,\r
702 IN EFI_PEI_LBA StartLBA,\r
703 IN UINTN BufferSize,\r
704 OUT VOID *Buffer\r
705 )\r
706{\r
707 EFI_STATUS Status;\r
708 UINTN BlockSize;\r
709 UINTN NumberOfBlocks;\r
710 UFS_PEIM_HC_PRIVATE_DATA *Private;\r
711 EFI_SCSI_SENSE_DATA SenseData;\r
712 UINT8 SenseDataLength;\r
d1102dba 713 BOOLEAN NeedRetry;\r
0591696e
FT
714\r
715 Status = EFI_SUCCESS;\r
716 NeedRetry = TRUE;\r
717 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
718\r
719 ZeroMem (&SenseData, sizeof (SenseData));\r
720 SenseDataLength = sizeof (SenseData);\r
721\r
722 //\r
723 // Check parameters\r
724 //\r
725 if (Buffer == NULL) {\r
726 return EFI_INVALID_PARAMETER;\r
727 }\r
728\r
729 if (BufferSize == 0) {\r
730 return EFI_SUCCESS;\r
731 }\r
732\r
733 if (DeviceIndex >= UFS_PEIM_MAX_LUNS) {\r
734 return EFI_INVALID_PARAMETER;\r
735 }\r
736\r
737 if ((Private->Luns.BitMask & (BIT0 << DeviceIndex)) == 0) {\r
738 return EFI_ACCESS_DENIED;\r
739 }\r
740\r
741 BlockSize = Private->Media[DeviceIndex].BlockSize;\r
742\r
743 if (BufferSize % BlockSize != 0) {\r
744 Status = EFI_BAD_BUFFER_SIZE;\r
745 }\r
746\r
747 if (StartLBA > Private->Media[DeviceIndex].LastBlock) {\r
748 Status = EFI_INVALID_PARAMETER;\r
749 }\r
750\r
751 NumberOfBlocks = BufferSize / BlockSize;\r
752\r
753 do {\r
754 Status = UfsPeimTestUnitReady (\r
755 Private,\r
756 DeviceIndex,\r
757 &SenseData,\r
758 &SenseDataLength\r
759 );\r
760 if (!EFI_ERROR (Status)) {\r
761 break;\r
762 }\r
d1102dba 763\r
0591696e
FT
764 if (SenseDataLength == 0) {\r
765 continue;\r
766 }\r
767\r
768 Status = UfsPeimParsingSenseKeys (&(Private->Media[DeviceIndex]), &SenseData, &NeedRetry);\r
769 if (EFI_ERROR (Status)) {\r
770 return EFI_DEVICE_ERROR;\r
771 }\r
772\r
773 } while (NeedRetry);\r
774\r
775 SenseDataLength = 0;\r
9d02f824 776 if (Private->Media[DeviceIndex].LastBlock < 0xfffffffful) {\r
0591696e
FT
777 Status = UfsPeimRead10 (\r
778 Private,\r
779 DeviceIndex,\r
780 (UINT32)StartLBA,\r
781 (UINT32)NumberOfBlocks,\r
782 Buffer,\r
783 (UINT32 *)&BufferSize,\r
784 NULL,\r
785 &SenseDataLength\r
786 );\r
787 } else {\r
788 Status = UfsPeimRead16 (\r
789 Private,\r
790 DeviceIndex,\r
791 (UINT32)StartLBA,\r
792 (UINT32)NumberOfBlocks,\r
793 Buffer,\r
794 (UINT32 *)&BufferSize,\r
795 NULL,\r
796 &SenseDataLength\r
797 );\r
798 }\r
799 return Status;\r
800}\r
801\r
9d02f824
FT
802/**\r
803 Gets the count of block I/O devices that one specific block driver detects.\r
804\r
d1102dba 805 This function is used for getting the count of block I/O devices that one\r
9d02f824 806 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
d1102dba
LG
807 of all the detected ATAPI devices it detects during the enumeration process.\r
808 To the PEI legacy floppy driver, it returns the number of all the legacy\r
809 devices it finds during its enumeration process. If no device is detected,\r
810 then the function will return zero.\r
811\r
812 @param[in] PeiServices General-purpose services that are available\r
9d02f824 813 to every PEIM.\r
d1102dba 814 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI\r
9d02f824
FT
815 instance.\r
816 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
817\r
818 @retval EFI_SUCCESS The operation performed successfully.\r
819\r
820**/\r
821EFI_STATUS\r
822EFIAPI\r
823UfsBlockIoPeimGetDeviceNo2 (\r
824 IN EFI_PEI_SERVICES **PeiServices,\r
825 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
826 OUT UINTN *NumberBlockDevices\r
827 )\r
828{\r
829 //\r
830 // For Ufs device, it has up to 8 normal Luns plus some well-known Luns.\r
831 // At PEI phase, we will only expose normal Luns to user.\r
832 // For those disabled Lun, when user try to access it, the operation would fail.\r
833 //\r
834 *NumberBlockDevices = UFS_PEIM_MAX_LUNS;\r
835 return EFI_SUCCESS;\r
836}\r
837\r
838/**\r
839 Gets a block device's media information.\r
840\r
d1102dba
LG
841 This function will provide the caller with the specified block device's media\r
842 information. If the media changes, calling this function will update the media\r
9d02f824
FT
843 information accordingly.\r
844\r
845 @param[in] PeiServices General-purpose services that are available to every\r
846 PEIM\r
847 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
d1102dba
LG
848 @param[in] DeviceIndex Specifies the block device to which the function wants\r
849 to talk. Because the driver that implements Block I/O\r
850 PPIs will manage multiple block devices, the PPIs that\r
851 want to talk to a single device must specify the\r
9d02f824 852 device index that was assigned during the enumeration\r
d1102dba 853 process. This index is a number from one to\r
9d02f824 854 NumberBlockDevices.\r
d1102dba
LG
855 @param[out] MediaInfo The media information of the specified block media.\r
856 The caller is responsible for the ownership of this\r
9d02f824
FT
857 data structure.\r
858\r
d1102dba
LG
859 @par Note:\r
860 The MediaInfo structure describes an enumeration of possible block device\r
861 types. This enumeration exists because no device paths are actually passed\r
862 across interfaces that describe the type or class of hardware that is publishing\r
9d02f824 863 the block I/O interface. This enumeration will allow for policy decisions\r
d1102dba
LG
864 in the Recovery PEIM, such as "Try to recover from legacy floppy first,\r
865 LS-120 second, CD-ROM third." If there are multiple partitions abstracted\r
866 by a given device type, they should be reported in ascending order; this\r
867 order also applies to nested partitions, such as legacy MBR, where the\r
868 outermost partitions would have precedence in the reporting order. The\r
869 same logic applies to systems such as IDE that have precedence relationships\r
870 like "Master/Slave" or "Primary/Secondary". The master device should be\r
9d02f824 871 reported first, the slave second.\r
d1102dba
LG
872\r
873 @retval EFI_SUCCESS Media information about the specified block device\r
9d02f824 874 was obtained successfully.\r
d1102dba 875 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
9d02f824
FT
876 error.\r
877\r
878**/\r
879EFI_STATUS\r
880EFIAPI\r
881UfsBlockIoPeimGetMediaInfo2 (\r
882 IN EFI_PEI_SERVICES **PeiServices,\r
883 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
884 IN UINTN DeviceIndex,\r
885 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo\r
886 )\r
887{\r
888 EFI_STATUS Status;\r
889 UFS_PEIM_HC_PRIVATE_DATA *Private;\r
890 EFI_PEI_BLOCK_IO_MEDIA Media;\r
891\r
892 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
d1102dba 893\r
9d02f824
FT
894 Status = UfsBlockIoPeimGetMediaInfo (\r
895 PeiServices,\r
896 &Private->BlkIoPpi,\r
897 DeviceIndex,\r
898 &Media\r
899 );\r
900 if (EFI_ERROR (Status)) {\r
901 return Status;\r
902 }\r
903\r
904 CopyMem (MediaInfo, &(Private->Media[DeviceIndex]), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));\r
905 return EFI_SUCCESS;\r
906}\r
907\r
908/**\r
909 Reads the requested number of blocks from the specified block device.\r
910\r
d1102dba 911 The function reads the requested number of blocks from the device. All the\r
9d02f824
FT
912 blocks are read, or an error is returned. If there is no media in the device,\r
913 the function returns EFI_NO_MEDIA.\r
914\r
d1102dba 915 @param[in] PeiServices General-purpose services that are available to\r
9d02f824
FT
916 every PEIM.\r
917 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
d1102dba
LG
918 @param[in] DeviceIndex Specifies the block device to which the function wants\r
919 to talk. Because the driver that implements Block I/O\r
920 PPIs will manage multiple block devices, PPIs that\r
921 want to talk to a single device must specify the device\r
922 index that was assigned during the enumeration process.\r
9d02f824
FT
923 This index is a number from one to NumberBlockDevices.\r
924 @param[in] StartLBA The starting logical block address (LBA) to read from\r
925 on the device\r
926 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
927 a multiple of the intrinsic block size of the device.\r
928 @param[out] Buffer A pointer to the destination buffer for the data.\r
d1102dba 929 The caller is responsible for the ownership of the\r
9d02f824 930 buffer.\r
d1102dba 931\r
9d02f824 932 @retval EFI_SUCCESS The data was read correctly from the device.\r
d1102dba 933 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
9d02f824 934 to perform the read operation.\r
d1102dba 935 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
9d02f824
FT
936 valid, or the buffer is not properly aligned.\r
937 @retval EFI_NO_MEDIA There is no media in the device.\r
938 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
939 the intrinsic block size of the device.\r
940\r
941**/\r
942EFI_STATUS\r
943EFIAPI\r
944UfsBlockIoPeimReadBlocks2 (\r
945 IN EFI_PEI_SERVICES **PeiServices,\r
946 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
947 IN UINTN DeviceIndex,\r
948 IN EFI_PEI_LBA StartLBA,\r
949 IN UINTN BufferSize,\r
950 OUT VOID *Buffer\r
951 )\r
952{\r
953 EFI_STATUS Status;\r
d1102dba 954 UFS_PEIM_HC_PRIVATE_DATA *Private;\r
9d02f824
FT
955\r
956 Status = EFI_SUCCESS;\r
957 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
958\r
959 Status = UfsBlockIoPeimReadBlocks (\r
960 PeiServices,\r
961 &Private->BlkIoPpi,\r
962 DeviceIndex,\r
963 StartLBA,\r
964 BufferSize,\r
965 Buffer\r
966 );\r
967 return Status;\r
968}\r
969\r
44a0857e
HW
970/**\r
971 One notified function to cleanup the allocated DMA buffers at the end of PEI.\r
972\r
973 @param[in] PeiServices Pointer to PEI Services Table.\r
974 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification\r
975 event that caused this function to execute.\r
976 @param[in] Ppi Pointer to the PPI data associated with this function.\r
977\r
978 @retval EFI_SUCCESS The function completes successfully\r
979\r
980**/\r
981EFI_STATUS\r
982EFIAPI\r
983UfsEndOfPei (\r
984 IN EFI_PEI_SERVICES **PeiServices,\r
985 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
986 IN VOID *Ppi\r
987 )\r
988{\r
989 UFS_PEIM_HC_PRIVATE_DATA *Private;\r
990\r
991 Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);\r
992\r
993 if ((Private->Pool != NULL) && (Private->Pool->Head != NULL)) {\r
994 UfsPeimFreeMemPool (Private->Pool);\r
995 }\r
996\r
997 if (Private->UtpTmrlBase != NULL) {\r
998 IoMmuFreeBuffer (\r
999 EFI_SIZE_TO_PAGES (Private->Nutmrs * sizeof (UTP_TMRD)),\r
1000 Private->UtpTmrlBase,\r
1001 Private->TmrlMapping\r
1002 );\r
1003 }\r
1004\r
1005 if (Private->UtpTrlBase != NULL) {\r
1006 IoMmuFreeBuffer (\r
1007 EFI_SIZE_TO_PAGES (Private->Nutrs * sizeof (UTP_TRD)),\r
1008 Private->UtpTrlBase,\r
1009 Private->TrlMapping\r
1010 );\r
1011 }\r
1012\r
1013 UfsControllerStop (Private);\r
1014\r
1015 return EFI_SUCCESS;\r
1016}\r
1017\r
0591696e
FT
1018/**\r
1019 The user code starts with this function.\r
d1102dba 1020\r
0591696e
FT
1021 @param FileHandle Handle of the file being invoked.\r
1022 @param PeiServices Describes the list of possible PEI Services.\r
1023\r
1024 @retval EFI_SUCCESS The driver is successfully initialized.\r
1025 @retval Others Can't initialize the driver.\r
1026\r
1027**/\r
1028EFI_STATUS\r
1029EFIAPI\r
1030InitializeUfsBlockIoPeim (\r
1031 IN EFI_PEI_FILE_HANDLE FileHandle,\r
1032 IN CONST EFI_PEI_SERVICES **PeiServices\r
1033 )\r
1034{\r
1035 EFI_STATUS Status;\r
1036 UFS_PEIM_HC_PRIVATE_DATA *Private;\r
1037 EDKII_UFS_HOST_CONTROLLER_PPI *UfsHcPpi;\r
1038 UINT32 Index;\r
1039 UFS_CONFIG_DESC Config;\r
1040 UINTN MmioBase;\r
1041 UINT8 Controller;\r
1042\r
1043 //\r
1044 // Shadow this PEIM to run from memory\r
1045 //\r
1046 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
1047 return EFI_SUCCESS;\r
1048 }\r
1049\r
1050 //\r
1051 // locate ufs host controller PPI\r
1052 //\r
1053 Status = PeiServicesLocatePpi (\r
1054 &gEdkiiPeiUfsHostControllerPpiGuid,\r
1055 0,\r
1056 NULL,\r
1057 (VOID **) &UfsHcPpi\r
1058 );\r
1059 if (EFI_ERROR (Status)) {\r
1060 return EFI_DEVICE_ERROR;\r
1061 }\r
1062\r
44a0857e
HW
1063 IoMmuInit ();\r
1064\r
0591696e
FT
1065 Controller = 0;\r
1066 MmioBase = 0;\r
1067 while (TRUE) {\r
1068 Status = UfsHcPpi->GetUfsHcMmioBar (UfsHcPpi, Controller, &MmioBase);\r
1069 //\r
1070 // When status is error, meant no controller is found\r
1071 //\r
1072 if (EFI_ERROR (Status)) {\r
1073 break;\r
1074 }\r
1075\r
1076 Private = AllocateCopyPool (sizeof (UFS_PEIM_HC_PRIVATE_DATA), &gUfsHcPeimTemplate);\r
1077 if (Private == NULL) {\r
1078 Status = EFI_OUT_OF_RESOURCES;\r
1079 break;\r
1080 }\r
1081\r
9d02f824
FT
1082 Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;\r
1083 Private->BlkIo2PpiList.Ppi = &Private->BlkIo2Ppi;\r
1084 Private->UfsHcBase = MmioBase;\r
0591696e
FT
1085\r
1086 //\r
1087 // Initialize the memory pool which will be used in all transactions.\r
1088 //\r
1089 Status = UfsPeimInitMemPool (Private);\r
1090 if (EFI_ERROR (Status)) {\r
1091 Status = EFI_OUT_OF_RESOURCES;\r
1092 break;\r
1093 }\r
1094\r
1095 //\r
1096 // Initialize UFS Host Controller H/W.\r
1097 //\r
1098 Status = UfsControllerInit (Private);\r
1099 if (EFI_ERROR (Status)) {\r
1100 DEBUG ((EFI_D_ERROR, "UfsDevicePei: Host Controller Initialization Error, Status = %r\n", Status));\r
1101 Controller++;\r
1102 continue;\r
1103 }\r
1104\r
1105 //\r
1106 // UFS 2.0 spec Section 13.1.3.3:\r
d1102dba
LG
1107 // At the end of the UFS Interconnect Layer initialization on both host and device side,\r
1108 // the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.\r
0591696e
FT
1109 //\r
1110 Status = UfsExecNopCmds (Private);\r
1111 if (EFI_ERROR (Status)) {\r
1112 DEBUG ((EFI_D_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));\r
1113 Controller++;\r
1114 continue;\r
1115 }\r
1116\r
1117 //\r
1118 // The host enables the device initialization completion by setting fDeviceInit flag.\r
1119 //\r
1120 Status = UfsSetFlag (Private, UfsFlagDevInit);\r
1121 if (EFI_ERROR (Status)) {\r
1122 DEBUG ((EFI_D_ERROR, "Ufs Set fDeviceInit Flag Error, Status = %r\n", Status));\r
1123 Controller++;\r
1124 continue;\r
1125 }\r
1126\r
1127 //\r
1128 // Get Ufs Device's Lun Info by reading Configuration Descriptor.\r
1129 //\r
1130 Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &Config, sizeof (UFS_CONFIG_DESC));\r
1131 if (EFI_ERROR (Status)) {\r
1132 DEBUG ((EFI_D_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));\r
1133 Controller++;\r
1134 continue;\r
1135 }\r
1136\r
1137 for (Index = 0; Index < UFS_PEIM_MAX_LUNS; Index++) {\r
1138 if (Config.UnitDescConfParams[Index].LunEn != 0) {\r
1139 Private->Luns.BitMask |= (BIT0 << Index);\r
1140 DEBUG ((EFI_D_INFO, "Ufs %d Lun %d is enabled\n", Controller, Index));\r
1141 }\r
1142 }\r
d1102dba 1143\r
44a0857e
HW
1144 PeiServicesInstallPpi (&Private->BlkIoPpiList);\r
1145 PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);\r
0591696e
FT
1146 Controller++;\r
1147 }\r
1148\r
1149 return EFI_SUCCESS;\r
1150}\r