]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c
MdeModulePkg/EmmcBlockIoPei: Support IoMmu
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / EmmcBlockIoPei / EmmcBlockIoPei.c
CommitLineData
48555339
FT
1/** @file\r
2\r
85ad9a6e 3 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
48555339
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 "EmmcBlockIoPei.h"\r
15\r
16//\r
17// Template for EMMC HC Slot Data.\r
18//\r
19EMMC_PEIM_HC_SLOT gEmmcHcSlotTemplate = {\r
20 EMMC_PEIM_SLOT_SIG, // Signature\r
21 { // Media\r
22 {\r
23 MSG_EMMC_DP,\r
24 FALSE,\r
25 TRUE,\r
26 FALSE,\r
27 0x200,\r
28 0\r
29 },\r
30 {\r
31 MSG_EMMC_DP,\r
32 FALSE,\r
33 TRUE,\r
34 FALSE,\r
35 0x200,\r
36 0\r
37 },\r
38 {\r
39 MSG_EMMC_DP,\r
40 FALSE,\r
41 TRUE,\r
42 FALSE,\r
43 0x200,\r
44 0\r
45 },\r
46 {\r
47 MSG_EMMC_DP,\r
48 FALSE,\r
49 TRUE,\r
50 FALSE,\r
51 0x200,\r
52 0\r
53 },\r
54 {\r
55 MSG_EMMC_DP,\r
56 FALSE,\r
57 TRUE,\r
58 FALSE,\r
59 0x200,\r
60 0\r
61 },\r
62 {\r
63 MSG_EMMC_DP,\r
64 FALSE,\r
65 TRUE,\r
66 FALSE,\r
67 0x200,\r
68 0\r
69 },\r
70 {\r
71 MSG_EMMC_DP,\r
72 FALSE,\r
73 TRUE,\r
74 FALSE,\r
75 0x200,\r
76 0\r
77 },\r
78 {\r
79 MSG_EMMC_DP,\r
80 FALSE,\r
81 TRUE,\r
82 FALSE,\r
83 0x200,\r
84 0\r
85 }\r
86 },\r
87 0, // MediaNum\r
88 { // PartitionType\r
89 EmmcPartitionUnknown,\r
90 EmmcPartitionUnknown,\r
91 EmmcPartitionUnknown,\r
92 EmmcPartitionUnknown,\r
93 EmmcPartitionUnknown,\r
94 EmmcPartitionUnknown,\r
95 EmmcPartitionUnknown,\r
96 EmmcPartitionUnknown\r
97 },\r
98 0, // EmmcHcBase\r
99 { // Capability\r
100 0,\r
101 },\r
102 { // Csd\r
103 0,\r
104 },\r
105 { // ExtCsd\r
106 {0},\r
107 },\r
108 TRUE, // SectorAddressing\r
109 NULL // Private\r
110};\r
111\r
112//\r
113// Template for EMMC HC Private Data.\r
114//\r
115EMMC_PEIM_HC_PRIVATE_DATA gEmmcHcPrivateTemplate = {\r
116 EMMC_PEIM_SIG, // Signature\r
117 NULL, // Pool\r
118 { // BlkIoPpi\r
119 EmmcBlockIoPeimGetDeviceNo,\r
120 EmmcBlockIoPeimGetMediaInfo,\r
121 EmmcBlockIoPeimReadBlocks\r
122 },\r
123 { // BlkIo2Ppi\r
124 EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,\r
125 EmmcBlockIoPeimGetDeviceNo2,\r
126 EmmcBlockIoPeimGetMediaInfo2,\r
127 EmmcBlockIoPeimReadBlocks2\r
128 },\r
129 { // BlkIoPpiList\r
130 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
131 &gEfiPeiVirtualBlockIoPpiGuid,\r
132 NULL\r
133 },\r
134 { // BlkIo2PpiList\r
135 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
136 &gEfiPeiVirtualBlockIo2PpiGuid,\r
137 NULL\r
138 },\r
85ad9a6e
HW
139 { // EndOfPeiNotifyList\r
140 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
141 &gEfiEndOfPeiSignalPpiGuid,\r
142 EmmcBlockIoPeimEndOfPei\r
143 },\r
48555339
FT
144 { // Slot\r
145 {\r
146 0,\r
147 },\r
148 {\r
149 0,\r
150 },\r
151 {\r
152 0,\r
153 },\r
154 {\r
155 0,\r
156 },\r
157 {\r
158 0,\r
159 },\r
160 {\r
161 0,\r
162 }\r
163 },\r
164 0, // SlotNum\r
165 0 // TotalBlkIoDevices\r
166};\r
167/**\r
168 Gets the count of block I/O devices that one specific block driver detects.\r
169\r
170 This function is used for getting the count of block I/O devices that one\r
171 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
172 of all the detected ATAPI devices it detects during the enumeration process.\r
173 To the PEI legacy floppy driver, it returns the number of all the legacy\r
174 devices it finds during its enumeration process. If no device is detected,\r
175 then the function will return zero.\r
176\r
177 @param[in] PeiServices General-purpose services that are available\r
178 to every PEIM.\r
179 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI\r
180 instance.\r
181 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
182\r
183 @retval EFI_SUCCESS The operation performed successfully.\r
184\r
185**/\r
186EFI_STATUS\r
187EFIAPI\r
188EmmcBlockIoPeimGetDeviceNo (\r
189 IN EFI_PEI_SERVICES **PeiServices,\r
190 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
191 OUT UINTN *NumberBlockDevices\r
192 )\r
193{\r
194 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
195\r
196 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
197 *NumberBlockDevices = Private->TotalBlkIoDevices;\r
198 return EFI_SUCCESS;\r
199}\r
200\r
201/**\r
202 Gets a block device's media information.\r
203\r
204 This function will provide the caller with the specified block device's media\r
205 information. If the media changes, calling this function will update the media\r
206 information accordingly.\r
207\r
208 @param[in] PeiServices General-purpose services that are available to every\r
209 PEIM\r
210 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
211 @param[in] DeviceIndex Specifies the block device to which the function wants\r
212 to talk. Because the driver that implements Block I/O\r
213 PPIs will manage multiple block devices, the PPIs that\r
214 want to talk to a single device must specify the\r
215 device index that was assigned during the enumeration\r
216 process. This index is a number from one to\r
217 NumberBlockDevices.\r
218 @param[out] MediaInfo The media information of the specified block media.\r
219 The caller is responsible for the ownership of this\r
220 data structure.\r
221\r
222 @par Note:\r
223 The MediaInfo structure describes an enumeration of possible block device\r
224 types. This enumeration exists because no device paths are actually passed\r
225 across interfaces that describe the type or class of hardware that is publishing\r
226 the block I/O interface. This enumeration will allow for policy decisions\r
227 in the Recovery PEIM, such as "Try to recover from legacy floppy first,\r
228 LS-120 second, CD-ROM third." If there are multiple partitions abstracted\r
229 by a given device type, they should be reported in ascending order; this\r
230 order also applies to nested partitions, such as legacy MBR, where the\r
231 outermost partitions would have precedence in the reporting order. The\r
232 same logic applies to systems such as IDE that have precedence relationships\r
233 like "Master/Slave" or "Primary/Secondary". The master device should be\r
234 reported first, the slave second.\r
235\r
236 @retval EFI_SUCCESS Media information about the specified block device\r
237 was obtained successfully.\r
238 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
239 error.\r
240\r
241**/\r
242EFI_STATUS\r
243EFIAPI\r
244EmmcBlockIoPeimGetMediaInfo (\r
245 IN EFI_PEI_SERVICES **PeiServices,\r
246 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
247 IN UINTN DeviceIndex,\r
248 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
249 )\r
250{\r
251 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
252 UINT8 SlotNum;\r
253 UINT8 MediaNum;\r
254 UINT8 Location;\r
255 BOOLEAN Found;\r
256\r
257 Found = FALSE;\r
258 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
259\r
260 if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {\r
261 return EFI_INVALID_PARAMETER;\r
262 }\r
263\r
264 Location = 0;\r
265 MediaNum = 0;\r
266 for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {\r
267 for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {\r
268 Location ++;\r
269 if (Location == DeviceIndex) {\r
270 Found = TRUE;\r
271 break;\r
272 }\r
273 }\r
274 if (Found) {\r
275 break;\r
276 }\r
277 }\r
278\r
279 MediaInfo->DeviceType = EMMC;\r
280 MediaInfo->MediaPresent = TRUE;\r
281 MediaInfo->LastBlock = (UINTN)Private->Slot[SlotNum].Media[MediaNum].LastBlock;\r
282 MediaInfo->BlockSize = Private->Slot[SlotNum].Media[MediaNum].BlockSize;\r
283\r
284 return EFI_SUCCESS;\r
285}\r
286\r
287/**\r
288 Reads the requested number of blocks from the specified block device.\r
289\r
290 The function reads the requested number of blocks from the device. All the\r
291 blocks are read, or an error is returned. If there is no media in the device,\r
292 the function returns EFI_NO_MEDIA.\r
293\r
294 @param[in] PeiServices General-purpose services that are available to\r
295 every PEIM.\r
296 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
297 @param[in] DeviceIndex Specifies the block device to which the function wants\r
298 to talk. Because the driver that implements Block I/O\r
299 PPIs will manage multiple block devices, PPIs that\r
300 want to talk to a single device must specify the device\r
301 index that was assigned during the enumeration process.\r
302 This index is a number from one to NumberBlockDevices.\r
303 @param[in] StartLBA The starting logical block address (LBA) to read from\r
304 on the device\r
305 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
306 a multiple of the intrinsic block size of the device.\r
307 @param[out] Buffer A pointer to the destination buffer for the data.\r
308 The caller is responsible for the ownership of the\r
309 buffer.\r
310\r
311 @retval EFI_SUCCESS The data was read correctly from the device.\r
312 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
313 to perform the read operation.\r
314 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
315 valid, or the buffer is not properly aligned.\r
316 @retval EFI_NO_MEDIA There is no media in the device.\r
317 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
318 the intrinsic block size of the device.\r
319\r
320**/\r
321EFI_STATUS\r
322EFIAPI\r
323EmmcBlockIoPeimReadBlocks (\r
324 IN EFI_PEI_SERVICES **PeiServices,\r
325 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
326 IN UINTN DeviceIndex,\r
327 IN EFI_PEI_LBA StartLBA,\r
328 IN UINTN BufferSize,\r
329 OUT VOID *Buffer\r
330 )\r
331{\r
332 EFI_STATUS Status;\r
333 UINT32 BlockSize;\r
334 UINTN NumberOfBlocks;\r
335 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
336 UINT8 SlotNum;\r
337 UINT8 MediaNum;\r
338 UINT8 Location;\r
339 UINT8 PartitionConfig;\r
340 UINTN Remaining;\r
341 UINT32 MaxBlock;\r
342 BOOLEAN Found;\r
343\r
344 Status = EFI_SUCCESS;\r
345 Found = FALSE;\r
346 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
347\r
348 //\r
349 // Check parameters\r
350 //\r
351 if (Buffer == NULL) {\r
352 return EFI_INVALID_PARAMETER;\r
353 }\r
354\r
355 if (BufferSize == 0) {\r
356 return EFI_SUCCESS;\r
357 }\r
358\r
359 if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {\r
360 return EFI_INVALID_PARAMETER;\r
361 }\r
362\r
363 Location = 0;\r
364 MediaNum = 0;\r
365 for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {\r
366 for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {\r
367 Location ++;\r
368 if (Location == DeviceIndex) {\r
369 Found = TRUE;\r
370 break;\r
371 }\r
372 }\r
373 if (Found) {\r
374 break;\r
375 }\r
376 }\r
377\r
378 BlockSize = Private->Slot[SlotNum].Media[MediaNum].BlockSize;\r
379 if (BufferSize % BlockSize != 0) {\r
380 return EFI_BAD_BUFFER_SIZE;\r
381 }\r
382\r
383 if (StartLBA > Private->Slot[SlotNum].Media[MediaNum].LastBlock) {\r
384 return EFI_INVALID_PARAMETER;\r
385 }\r
386\r
387 NumberOfBlocks = BufferSize / BlockSize;\r
388\r
389 //\r
390 // Check if needs to switch partition access.\r
391 //\r
392 PartitionConfig = Private->Slot[SlotNum].ExtCsd.PartitionConfig;\r
393 if ((PartitionConfig & 0x7) != Private->Slot[SlotNum].PartitionType[MediaNum]) {\r
394 PartitionConfig &= (UINT8)~0x7;\r
395 PartitionConfig |= Private->Slot[SlotNum].PartitionType[MediaNum];\r
396 Status = EmmcPeimSwitch (\r
397 &Private->Slot[SlotNum],\r
398 0x3,\r
399 OFFSET_OF (EMMC_EXT_CSD, PartitionConfig),\r
400 PartitionConfig,\r
401 0x0\r
402 );\r
403 if (EFI_ERROR (Status)) {\r
404 return Status;\r
405 }\r
406 Private->Slot[SlotNum].ExtCsd.PartitionConfig = PartitionConfig;\r
407 }\r
408 //\r
409 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.\r
410 //\r
411 Remaining = NumberOfBlocks;\r
412 MaxBlock = 0xFFFF;\r
413\r
414 while (Remaining > 0) {\r
415 if (Remaining <= MaxBlock) {\r
416 NumberOfBlocks = Remaining;\r
417 } else {\r
418 NumberOfBlocks = MaxBlock;\r
419 }\r
420\r
421 Status = EmmcPeimSetBlkCount (&Private->Slot[SlotNum], (UINT16)NumberOfBlocks);\r
422 if (EFI_ERROR (Status)) {\r
423 return Status;\r
424 }\r
425\r
426 BufferSize = NumberOfBlocks * BlockSize;\r
427 Status = EmmcPeimRwMultiBlocks (&Private->Slot[SlotNum], StartLBA, BlockSize, Buffer, BufferSize, TRUE);\r
428 if (EFI_ERROR (Status)) {\r
429 return Status;\r
430 }\r
431\r
432 StartLBA += NumberOfBlocks;\r
433 Buffer = (UINT8*)Buffer + BufferSize;\r
434 Remaining -= NumberOfBlocks;\r
435 }\r
436 return Status;\r
437}\r
438\r
439/**\r
440 Gets the count of block I/O devices that one specific block driver detects.\r
441\r
442 This function is used for getting the count of block I/O devices that one\r
443 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
444 of all the detected ATAPI devices it detects during the enumeration process.\r
445 To the PEI legacy floppy driver, it returns the number of all the legacy\r
446 devices it finds during its enumeration process. If no device is detected,\r
447 then the function will return zero.\r
448\r
449 @param[in] PeiServices General-purpose services that are available\r
450 to every PEIM.\r
451 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI\r
452 instance.\r
453 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
454\r
455 @retval EFI_SUCCESS The operation performed successfully.\r
456\r
457**/\r
458EFI_STATUS\r
459EFIAPI\r
460EmmcBlockIoPeimGetDeviceNo2 (\r
461 IN EFI_PEI_SERVICES **PeiServices,\r
462 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
463 OUT UINTN *NumberBlockDevices\r
464 )\r
465{\r
466 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
467\r
468 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
469 *NumberBlockDevices = Private->TotalBlkIoDevices;\r
470\r
471 return EFI_SUCCESS;\r
472}\r
473\r
474/**\r
475 Gets a block device's media information.\r
476\r
477 This function will provide the caller with the specified block device's media\r
478 information. If the media changes, calling this function will update the media\r
479 information accordingly.\r
480\r
481 @param[in] PeiServices General-purpose services that are available to every\r
482 PEIM\r
483 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
484 @param[in] DeviceIndex Specifies the block device to which the function wants\r
485 to talk. Because the driver that implements Block I/O\r
486 PPIs will manage multiple block devices, the PPIs that\r
487 want to talk to a single device must specify the\r
488 device index that was assigned during the enumeration\r
489 process. This index is a number from one to\r
490 NumberBlockDevices.\r
491 @param[out] MediaInfo The media information of the specified block media.\r
492 The caller is responsible for the ownership of this\r
493 data structure.\r
494\r
495 @par Note:\r
496 The MediaInfo structure describes an enumeration of possible block device\r
497 types. This enumeration exists because no device paths are actually passed\r
498 across interfaces that describe the type or class of hardware that is publishing\r
499 the block I/O interface. This enumeration will allow for policy decisions\r
500 in the Recovery PEIM, such as "Try to recover from legacy floppy first,\r
501 LS-120 second, CD-ROM third." If there are multiple partitions abstracted\r
502 by a given device type, they should be reported in ascending order; this\r
503 order also applies to nested partitions, such as legacy MBR, where the\r
504 outermost partitions would have precedence in the reporting order. The\r
505 same logic applies to systems such as IDE that have precedence relationships\r
506 like "Master/Slave" or "Primary/Secondary". The master device should be\r
507 reported first, the slave second.\r
508\r
509 @retval EFI_SUCCESS Media information about the specified block device\r
510 was obtained successfully.\r
511 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
512 error.\r
513\r
514**/\r
515EFI_STATUS\r
516EFIAPI\r
517EmmcBlockIoPeimGetMediaInfo2 (\r
518 IN EFI_PEI_SERVICES **PeiServices,\r
519 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
520 IN UINTN DeviceIndex,\r
521 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo\r
522 )\r
523{\r
524 EFI_STATUS Status;\r
525 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
526 EFI_PEI_BLOCK_IO_MEDIA Media;\r
527 UINT8 SlotNum;\r
528 UINT8 MediaNum;\r
529 UINT8 Location;\r
530 BOOLEAN Found;\r
531\r
532 Found = FALSE;\r
533 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
534\r
535 Status = EmmcBlockIoPeimGetMediaInfo (\r
536 PeiServices,\r
537 &Private->BlkIoPpi,\r
538 DeviceIndex,\r
539 &Media\r
540 );\r
541 if (EFI_ERROR (Status)) {\r
542 return Status;\r
543 }\r
544\r
545 Location = 0;\r
546 MediaNum = 0;\r
547 for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {\r
548 for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {\r
549 Location ++;\r
550 if (Location == DeviceIndex) {\r
551 Found = TRUE;\r
552 break;\r
553 }\r
554 }\r
555 if (Found) {\r
556 break;\r
557 }\r
558 }\r
559\r
560 CopyMem (MediaInfo, &(Private->Slot[SlotNum].Media[MediaNum]), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));\r
561 return EFI_SUCCESS;\r
562}\r
563\r
564/**\r
565 Reads the requested number of blocks from the specified block device.\r
566\r
567 The function reads the requested number of blocks from the device. All the\r
568 blocks are read, or an error is returned. If there is no media in the device,\r
569 the function returns EFI_NO_MEDIA.\r
570\r
571 @param[in] PeiServices General-purpose services that are available to\r
572 every PEIM.\r
573 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
574 @param[in] DeviceIndex Specifies the block device to which the function wants\r
575 to talk. Because the driver that implements Block I/O\r
576 PPIs will manage multiple block devices, PPIs that\r
577 want to talk to a single device must specify the device\r
578 index that was assigned during the enumeration process.\r
579 This index is a number from one to NumberBlockDevices.\r
580 @param[in] StartLBA The starting logical block address (LBA) to read from\r
581 on the device\r
582 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
583 a multiple of the intrinsic block size of the device.\r
584 @param[out] Buffer A pointer to the destination buffer for the data.\r
585 The caller is responsible for the ownership of the\r
586 buffer.\r
587\r
588 @retval EFI_SUCCESS The data was read correctly from the device.\r
589 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
590 to perform the read operation.\r
591 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
592 valid, or the buffer is not properly aligned.\r
593 @retval EFI_NO_MEDIA There is no media in the device.\r
594 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
595 the intrinsic block size of the device.\r
596\r
597**/\r
598EFI_STATUS\r
599EFIAPI\r
600EmmcBlockIoPeimReadBlocks2 (\r
601 IN EFI_PEI_SERVICES **PeiServices,\r
602 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
603 IN UINTN DeviceIndex,\r
604 IN EFI_PEI_LBA StartLBA,\r
605 IN UINTN BufferSize,\r
606 OUT VOID *Buffer\r
607 )\r
608{\r
609 EFI_STATUS Status;\r
610 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
611\r
612 Status = EFI_SUCCESS;\r
613 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
614\r
615 Status = EmmcBlockIoPeimReadBlocks (\r
616 PeiServices,\r
617 &Private->BlkIoPpi,\r
618 DeviceIndex,\r
619 StartLBA,\r
620 BufferSize,\r
621 Buffer\r
622 );\r
623 return Status;\r
624}\r
625\r
85ad9a6e
HW
626/**\r
627 One notified function to cleanup the allocated DMA buffers at the end of PEI.\r
628\r
629 @param[in] PeiServices Pointer to PEI Services Table.\r
630 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification\r
631 event that caused this function to execute.\r
632 @param[in] Ppi Pointer to the PPI data associated with this function.\r
633\r
634 @retval EFI_SUCCESS The function completes successfully\r
635\r
636**/\r
637EFI_STATUS\r
638EFIAPI\r
639EmmcBlockIoPeimEndOfPei (\r
640 IN EFI_PEI_SERVICES **PeiServices,\r
641 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
642 IN VOID *Ppi\r
643 )\r
644{\r
645 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
646\r
647 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);\r
648\r
649 if ((Private->Pool != NULL) && (Private->Pool->Head != NULL)) {\r
650 EmmcPeimFreeMemPool (Private->Pool);\r
651 }\r
652\r
653 return EFI_SUCCESS;\r
654}\r
655\r
48555339
FT
656/**\r
657 The user code starts with this function.\r
658\r
659 @param FileHandle Handle of the file being invoked.\r
660 @param PeiServices Describes the list of possible PEI Services.\r
661\r
662 @retval EFI_SUCCESS The driver is successfully initialized.\r
663 @retval Others Can't initialize the driver.\r
664\r
665**/\r
666EFI_STATUS\r
667EFIAPI\r
668InitializeEmmcBlockIoPeim (\r
669 IN EFI_PEI_FILE_HANDLE FileHandle,\r
670 IN CONST EFI_PEI_SERVICES **PeiServices\r
671 )\r
672{\r
673 EFI_STATUS Status;\r
674 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
675 EDKII_SD_MMC_HOST_CONTROLLER_PPI *SdMmcHcPpi;\r
676 UINT32 Index;\r
677 UINT32 PartitionIndex;\r
678 UINTN *MmioBase;\r
679 UINT8 BarNum;\r
680 UINT8 SlotNum;\r
681 UINT8 MediaNum;\r
682 UINT8 Controller;\r
683 UINT64 Capacity;\r
684 EMMC_EXT_CSD *ExtCsd;\r
685 EMMC_HC_SLOT_CAP Capability;\r
686 EMMC_PEIM_HC_SLOT *Slot;\r
687 UINT32 SecCount;\r
688 UINT32 GpSizeMult;\r
689\r
690 //\r
691 // Shadow this PEIM to run from memory\r
692 //\r
693 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
694 return EFI_SUCCESS;\r
695 }\r
696\r
697 //\r
698 // locate Emmc host controller PPI\r
699 //\r
700 Status = PeiServicesLocatePpi (\r
701 &gEdkiiPeiSdMmcHostControllerPpiGuid,\r
702 0,\r
703 NULL,\r
704 (VOID **) &SdMmcHcPpi\r
705 );\r
706 if (EFI_ERROR (Status)) {\r
707 return EFI_DEVICE_ERROR;\r
708 }\r
709\r
85ad9a6e
HW
710 IoMmuInit ();\r
711\r
48555339
FT
712 Controller = 0;\r
713 MmioBase = NULL;\r
714 while (TRUE) {\r
715 Status = SdMmcHcPpi->GetSdMmcHcMmioBar (SdMmcHcPpi, Controller, &MmioBase, &BarNum);\r
716 //\r
717 // When status is error, meant no controller is found\r
718 //\r
719 if (EFI_ERROR (Status)) {\r
720 break;\r
721 }\r
722\r
723 if (BarNum == 0) {\r
724 Controller++;\r
725 continue;\r
726 }\r
727\r
728 Private = AllocateCopyPool (sizeof (EMMC_PEIM_HC_PRIVATE_DATA), &gEmmcHcPrivateTemplate);\r
729 if (Private == NULL) {\r
730 Status = EFI_OUT_OF_RESOURCES;\r
731 break;\r
732 }\r
733 Private->BlkIoPpiList.Ppi = (VOID*)&Private->BlkIoPpi;\r
734 Private->BlkIo2PpiList.Ppi = (VOID*)&Private->BlkIo2Ppi;\r
735 //\r
736 // Initialize the memory pool which will be used in all transactions.\r
737 //\r
738 Status = EmmcPeimInitMemPool (Private);\r
739 if (EFI_ERROR (Status)) {\r
740 Status = EFI_OUT_OF_RESOURCES;\r
741 break;\r
742 }\r
743\r
744 for (Index = 0; Index < BarNum; Index++) {\r
745 Status = EmmcPeimHcGetCapability (MmioBase[Index], &Capability);\r
746 if (EFI_ERROR (Status)) {\r
747 continue;\r
748 }\r
749 if (Capability.SlotType != 0x1) {\r
750 DEBUG ((EFI_D_INFO, "The slot at 0x%x is not embedded slot type\n", MmioBase[Index]));\r
751 Status = EFI_UNSUPPORTED;\r
752 continue;\r
753 }\r
754\r
755 Status = EmmcPeimHcReset (MmioBase[Index]);\r
756 if (EFI_ERROR (Status)) {\r
757 continue;\r
758 }\r
759 Status = EmmcPeimHcCardDetect (MmioBase[Index]);\r
760 if (EFI_ERROR (Status)) {\r
761 continue;\r
762 }\r
763 Status = EmmcPeimHcInitHost (MmioBase[Index]);\r
764 if (EFI_ERROR (Status)) {\r
765 continue;\r
766 }\r
767\r
768 SlotNum = Private->SlotNum;\r
769 Slot = &Private->Slot[SlotNum];\r
770 CopyMem (Slot, &gEmmcHcSlotTemplate, sizeof (EMMC_PEIM_HC_SLOT));\r
771 Slot->Private = Private;\r
772 Slot->EmmcHcBase = MmioBase[Index];\r
773 CopyMem (&Slot->Capability, &Capability, sizeof (Capability));\r
774\r
775 Status = EmmcPeimIdentification (Slot);\r
776 if (EFI_ERROR (Status)) {\r
777 continue;\r
778 }\r
779\r
780 ExtCsd = &Slot->ExtCsd;\r
781 if (ExtCsd->ExtCsdRev < 5) {\r
782 DEBUG ((EFI_D_ERROR, "The EMMC device version is too low, we don't support!!!\n"));\r
783 Status = EFI_UNSUPPORTED;\r
784 continue;\r
785 }\r
786 if ((ExtCsd->PartitioningSupport & BIT0) != BIT0) {\r
787 DEBUG ((EFI_D_ERROR, "The EMMC device doesn't support Partition Feature!!!\n"));\r
788 Status = EFI_UNSUPPORTED;\r
789 continue;\r
790 }\r
791\r
792 for (PartitionIndex = 0; PartitionIndex < EMMC_PEIM_MAX_PARTITIONS; PartitionIndex++) {\r
793 switch (PartitionIndex) {\r
794 case EmmcPartitionUserData:\r
795 SecCount = *(UINT32*)&ExtCsd->SecCount;\r
796 Capacity = MultU64x32 ((UINT64)SecCount, 0x200);\r
797 break;\r
798 case EmmcPartitionBoot1:\r
799 case EmmcPartitionBoot2:\r
800 Capacity = ExtCsd->BootSizeMult * SIZE_128KB;\r
801 break;\r
802 case EmmcPartitionRPMB:\r
803 Capacity = ExtCsd->RpmbSizeMult * SIZE_128KB;\r
804 break;\r
805 case EmmcPartitionGP1:\r
806 GpSizeMult = (ExtCsd->GpSizeMult[0] | (ExtCsd->GpSizeMult[1] << 8) | (ExtCsd->GpSizeMult[2] << 16));\r
807 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
808 break;\r
809 case EmmcPartitionGP2:\r
810 GpSizeMult = (ExtCsd->GpSizeMult[3] | (ExtCsd->GpSizeMult[4] << 8) | (ExtCsd->GpSizeMult[5] << 16));\r
811 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
812 break;\r
813 case EmmcPartitionGP3:\r
814 GpSizeMult = (ExtCsd->GpSizeMult[6] | (ExtCsd->GpSizeMult[7] << 8) | (ExtCsd->GpSizeMult[8] << 16));\r
815 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
816 break;\r
817 case EmmcPartitionGP4:\r
818 GpSizeMult = (ExtCsd->GpSizeMult[9] | (ExtCsd->GpSizeMult[10] << 8) | (ExtCsd->GpSizeMult[11] << 16));\r
819 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
820 break;\r
821 default:\r
822 ASSERT (FALSE);\r
823 continue;\r
824 }\r
825\r
826 MediaNum = Slot->MediaNum;\r
827 if (Capacity != 0) {\r
828 Slot->Media[MediaNum].LastBlock = DivU64x32 (Capacity, Slot->Media[MediaNum].BlockSize) - 1;\r
829 Slot->PartitionType[MediaNum] = PartitionIndex;\r
830 Private->TotalBlkIoDevices++;\r
831 Slot->MediaNum++;\r
832 }\r
833 }\r
834 Private->SlotNum++;\r
835 }\r
836 Controller++;\r
837\r
838 if (!EFI_ERROR (Status)) {\r
839 PeiServicesInstallPpi (&Private->BlkIoPpiList);\r
85ad9a6e
HW
840 PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);\r
841 } else {\r
842 if (Private->Pool->Head != NULL) {\r
843 EmmcPeimFreeMemPool (Private->Pool);\r
844 }\r
48555339
FT
845 }\r
846 }\r
847\r
848 return EFI_SUCCESS;\r
849}\r