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