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