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