]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c
MdeModulePkg EmmcDxe: Fix GCC build failure with set but unused variables
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / EmmcBlockIoPei / EmmcBlockIoPei.c
CommitLineData
48555339
FT
1/** @file\r
2\r
3 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
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
139 { // Slot\r
140 {\r
141 0,\r
142 },\r
143 {\r
144 0,\r
145 },\r
146 {\r
147 0,\r
148 },\r
149 {\r
150 0,\r
151 },\r
152 {\r
153 0,\r
154 },\r
155 {\r
156 0,\r
157 }\r
158 },\r
159 0, // SlotNum\r
160 0 // TotalBlkIoDevices\r
161};\r
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
189 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
190\r
191 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
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
246 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
247 UINT8 SlotNum;\r
248 UINT8 MediaNum;\r
249 UINT8 Location;\r
250 BOOLEAN Found;\r
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
263 Location ++;\r
264 if (Location == DeviceIndex) {\r
265 Found = TRUE;\r
266 break;\r
267 }\r
268 }\r
269 if (Found) {\r
270 break;\r
271 }\r
272 }\r
273\r
274 MediaInfo->DeviceType = EMMC;\r
275 MediaInfo->MediaPresent = TRUE;\r
276 MediaInfo->LastBlock = (UINTN)Private->Slot[SlotNum].Media[MediaNum].LastBlock;\r
277 MediaInfo->BlockSize = Private->Slot[SlotNum].Media[MediaNum].BlockSize;\r
278\r
279 return EFI_SUCCESS;\r
280}\r
281\r
282/**\r
283 Reads the requested number of blocks from the specified block device.\r
284\r
285 The function reads the requested number of blocks from the device. All the\r
286 blocks are read, or an error is returned. If there is no media in the device,\r
287 the function returns EFI_NO_MEDIA.\r
288\r
289 @param[in] PeiServices General-purpose services that are available to\r
290 every PEIM.\r
291 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
292 @param[in] DeviceIndex Specifies the block device to which the function wants\r
293 to talk. Because the driver that implements Block I/O\r
294 PPIs will manage multiple block devices, PPIs that\r
295 want to talk to a single device must specify the device\r
296 index that was assigned during the enumeration process.\r
297 This index is a number from one to NumberBlockDevices.\r
298 @param[in] StartLBA The starting logical block address (LBA) to read from\r
299 on the device\r
300 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
301 a multiple of the intrinsic block size of the device.\r
302 @param[out] Buffer A pointer to the destination buffer for the data.\r
303 The caller is responsible for the ownership of the\r
304 buffer.\r
305\r
306 @retval EFI_SUCCESS The data was read correctly from the device.\r
307 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
308 to perform the read operation.\r
309 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
310 valid, or the buffer is not properly aligned.\r
311 @retval EFI_NO_MEDIA There is no media in the device.\r
312 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
313 the intrinsic block size of the device.\r
314\r
315**/\r
316EFI_STATUS\r
317EFIAPI\r
318EmmcBlockIoPeimReadBlocks (\r
319 IN EFI_PEI_SERVICES **PeiServices,\r
320 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
321 IN UINTN DeviceIndex,\r
322 IN EFI_PEI_LBA StartLBA,\r
323 IN UINTN BufferSize,\r
324 OUT VOID *Buffer\r
325 )\r
326{\r
327 EFI_STATUS Status;\r
328 UINT32 BlockSize;\r
329 UINTN NumberOfBlocks;\r
330 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
331 UINT8 SlotNum;\r
332 UINT8 MediaNum;\r
333 UINT8 Location;\r
334 UINT8 PartitionConfig;\r
335 UINTN Remaining;\r
336 UINT32 MaxBlock;\r
337 BOOLEAN Found;\r
338\r
339 Status = EFI_SUCCESS;\r
340 Found = FALSE;\r
341 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
342\r
343 //\r
344 // Check parameters\r
345 //\r
346 if (Buffer == NULL) {\r
347 return EFI_INVALID_PARAMETER;\r
348 }\r
349\r
350 if (BufferSize == 0) {\r
351 return EFI_SUCCESS;\r
352 }\r
353\r
354 if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {\r
355 return EFI_INVALID_PARAMETER;\r
356 }\r
357\r
358 Location = 0;\r
359 MediaNum = 0;\r
360 for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {\r
361 for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {\r
362 Location ++;\r
363 if (Location == DeviceIndex) {\r
364 Found = TRUE;\r
365 break;\r
366 }\r
367 }\r
368 if (Found) {\r
369 break;\r
370 }\r
371 }\r
372\r
373 BlockSize = Private->Slot[SlotNum].Media[MediaNum].BlockSize;\r
374 if (BufferSize % BlockSize != 0) {\r
375 return EFI_BAD_BUFFER_SIZE;\r
376 }\r
377\r
378 if (StartLBA > Private->Slot[SlotNum].Media[MediaNum].LastBlock) {\r
379 return EFI_INVALID_PARAMETER;\r
380 }\r
381\r
382 NumberOfBlocks = BufferSize / BlockSize;\r
383\r
384 //\r
385 // Check if needs to switch partition access.\r
386 //\r
387 PartitionConfig = Private->Slot[SlotNum].ExtCsd.PartitionConfig;\r
388 if ((PartitionConfig & 0x7) != Private->Slot[SlotNum].PartitionType[MediaNum]) {\r
389 PartitionConfig &= (UINT8)~0x7;\r
390 PartitionConfig |= Private->Slot[SlotNum].PartitionType[MediaNum];\r
391 Status = EmmcPeimSwitch (\r
392 &Private->Slot[SlotNum],\r
393 0x3,\r
394 OFFSET_OF (EMMC_EXT_CSD, PartitionConfig),\r
395 PartitionConfig,\r
396 0x0\r
397 );\r
398 if (EFI_ERROR (Status)) {\r
399 return Status;\r
400 }\r
401 Private->Slot[SlotNum].ExtCsd.PartitionConfig = PartitionConfig;\r
402 }\r
403 //\r
404 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.\r
405 //\r
406 Remaining = NumberOfBlocks;\r
407 MaxBlock = 0xFFFF;\r
408\r
409 while (Remaining > 0) {\r
410 if (Remaining <= MaxBlock) {\r
411 NumberOfBlocks = Remaining;\r
412 } else {\r
413 NumberOfBlocks = MaxBlock;\r
414 }\r
415\r
416 Status = EmmcPeimSetBlkCount (&Private->Slot[SlotNum], (UINT16)NumberOfBlocks);\r
417 if (EFI_ERROR (Status)) {\r
418 return Status;\r
419 }\r
420\r
421 BufferSize = NumberOfBlocks * BlockSize;\r
422 Status = EmmcPeimRwMultiBlocks (&Private->Slot[SlotNum], StartLBA, BlockSize, Buffer, BufferSize, TRUE);\r
423 if (EFI_ERROR (Status)) {\r
424 return Status;\r
425 }\r
426\r
427 StartLBA += NumberOfBlocks;\r
428 Buffer = (UINT8*)Buffer + BufferSize;\r
429 Remaining -= NumberOfBlocks;\r
430 }\r
431 return Status;\r
432}\r
433\r
434/**\r
435 Gets the count of block I/O devices that one specific block driver detects.\r
436\r
437 This function is used for getting the count of block I/O devices that one\r
438 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
439 of all the detected ATAPI devices it detects during the enumeration process.\r
440 To the PEI legacy floppy driver, it returns the number of all the legacy\r
441 devices it finds during its enumeration process. If no device is detected,\r
442 then the function will return zero.\r
443\r
444 @param[in] PeiServices General-purpose services that are available\r
445 to every PEIM.\r
446 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI\r
447 instance.\r
448 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
449\r
450 @retval EFI_SUCCESS The operation performed successfully.\r
451\r
452**/\r
453EFI_STATUS\r
454EFIAPI\r
455EmmcBlockIoPeimGetDeviceNo2 (\r
456 IN EFI_PEI_SERVICES **PeiServices,\r
457 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
458 OUT UINTN *NumberBlockDevices\r
459 )\r
460{\r
461 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
462\r
463 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
464 *NumberBlockDevices = Private->TotalBlkIoDevices;\r
465\r
466 return EFI_SUCCESS;\r
467}\r
468\r
469/**\r
470 Gets a block device's media information.\r
471\r
472 This function will provide the caller with the specified block device's media\r
473 information. If the media changes, calling this function will update the media\r
474 information accordingly.\r
475\r
476 @param[in] PeiServices General-purpose services that are available to every\r
477 PEIM\r
478 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
479 @param[in] DeviceIndex Specifies the block device to which the function wants\r
480 to talk. Because the driver that implements Block I/O\r
481 PPIs will manage multiple block devices, the PPIs that\r
482 want to talk to a single device must specify the\r
483 device index that was assigned during the enumeration\r
484 process. This index is a number from one to\r
485 NumberBlockDevices.\r
486 @param[out] MediaInfo The media information of the specified block media.\r
487 The caller is responsible for the ownership of this\r
488 data structure.\r
489\r
490 @par Note:\r
491 The MediaInfo structure describes an enumeration of possible block device\r
492 types. This enumeration exists because no device paths are actually passed\r
493 across interfaces that describe the type or class of hardware that is publishing\r
494 the block I/O interface. This enumeration will allow for policy decisions\r
495 in the Recovery PEIM, such as "Try to recover from legacy floppy first,\r
496 LS-120 second, CD-ROM third." If there are multiple partitions abstracted\r
497 by a given device type, they should be reported in ascending order; this\r
498 order also applies to nested partitions, such as legacy MBR, where the\r
499 outermost partitions would have precedence in the reporting order. The\r
500 same logic applies to systems such as IDE that have precedence relationships\r
501 like "Master/Slave" or "Primary/Secondary". The master device should be\r
502 reported first, the slave second.\r
503\r
504 @retval EFI_SUCCESS Media information about the specified block device\r
505 was obtained successfully.\r
506 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
507 error.\r
508\r
509**/\r
510EFI_STATUS\r
511EFIAPI\r
512EmmcBlockIoPeimGetMediaInfo2 (\r
513 IN EFI_PEI_SERVICES **PeiServices,\r
514 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
515 IN UINTN DeviceIndex,\r
516 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo\r
517 )\r
518{\r
519 EFI_STATUS Status;\r
520 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
521 EFI_PEI_BLOCK_IO_MEDIA Media;\r
522 UINT8 SlotNum;\r
523 UINT8 MediaNum;\r
524 UINT8 Location;\r
525 BOOLEAN Found;\r
526\r
527 Found = FALSE;\r
528 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
529\r
530 Status = EmmcBlockIoPeimGetMediaInfo (\r
531 PeiServices,\r
532 &Private->BlkIoPpi,\r
533 DeviceIndex,\r
534 &Media\r
535 );\r
536 if (EFI_ERROR (Status)) {\r
537 return Status;\r
538 }\r
539\r
540 Location = 0;\r
541 MediaNum = 0;\r
542 for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {\r
543 for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {\r
544 Location ++;\r
545 if (Location == DeviceIndex) {\r
546 Found = TRUE;\r
547 break;\r
548 }\r
549 }\r
550 if (Found) {\r
551 break;\r
552 }\r
553 }\r
554\r
555 CopyMem (MediaInfo, &(Private->Slot[SlotNum].Media[MediaNum]), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));\r
556 return EFI_SUCCESS;\r
557}\r
558\r
559/**\r
560 Reads the requested number of blocks from the specified block device.\r
561\r
562 The function reads the requested number of blocks from the device. All the\r
563 blocks are read, or an error is returned. If there is no media in the device,\r
564 the function returns EFI_NO_MEDIA.\r
565\r
566 @param[in] PeiServices General-purpose services that are available to\r
567 every PEIM.\r
568 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
569 @param[in] DeviceIndex Specifies the block device to which the function wants\r
570 to talk. Because the driver that implements Block I/O\r
571 PPIs will manage multiple block devices, PPIs that\r
572 want to talk to a single device must specify the device\r
573 index that was assigned during the enumeration process.\r
574 This index is a number from one to NumberBlockDevices.\r
575 @param[in] StartLBA The starting logical block address (LBA) to read from\r
576 on the device\r
577 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
578 a multiple of the intrinsic block size of the device.\r
579 @param[out] Buffer A pointer to the destination buffer for the data.\r
580 The caller is responsible for the ownership of the\r
581 buffer.\r
582\r
583 @retval EFI_SUCCESS The data was read correctly from the device.\r
584 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
585 to perform the read operation.\r
586 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
587 valid, or the buffer is not properly aligned.\r
588 @retval EFI_NO_MEDIA There is no media in the device.\r
589 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
590 the intrinsic block size of the device.\r
591\r
592**/\r
593EFI_STATUS\r
594EFIAPI\r
595EmmcBlockIoPeimReadBlocks2 (\r
596 IN EFI_PEI_SERVICES **PeiServices,\r
597 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
598 IN UINTN DeviceIndex,\r
599 IN EFI_PEI_LBA StartLBA,\r
600 IN UINTN BufferSize,\r
601 OUT VOID *Buffer\r
602 )\r
603{\r
604 EFI_STATUS Status;\r
605 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
606\r
607 Status = EFI_SUCCESS;\r
608 Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
609\r
610 Status = EmmcBlockIoPeimReadBlocks (\r
611 PeiServices,\r
612 &Private->BlkIoPpi,\r
613 DeviceIndex,\r
614 StartLBA,\r
615 BufferSize,\r
616 Buffer\r
617 );\r
618 return Status;\r
619}\r
620\r
621/**\r
622 The user code starts with this function.\r
623\r
624 @param FileHandle Handle of the file being invoked.\r
625 @param PeiServices Describes the list of possible PEI Services.\r
626\r
627 @retval EFI_SUCCESS The driver is successfully initialized.\r
628 @retval Others Can't initialize the driver.\r
629\r
630**/\r
631EFI_STATUS\r
632EFIAPI\r
633InitializeEmmcBlockIoPeim (\r
634 IN EFI_PEI_FILE_HANDLE FileHandle,\r
635 IN CONST EFI_PEI_SERVICES **PeiServices\r
636 )\r
637{\r
638 EFI_STATUS Status;\r
639 EMMC_PEIM_HC_PRIVATE_DATA *Private;\r
640 EDKII_SD_MMC_HOST_CONTROLLER_PPI *SdMmcHcPpi;\r
641 UINT32 Index;\r
642 UINT32 PartitionIndex;\r
643 UINTN *MmioBase;\r
644 UINT8 BarNum;\r
645 UINT8 SlotNum;\r
646 UINT8 MediaNum;\r
647 UINT8 Controller;\r
648 UINT64 Capacity;\r
649 EMMC_EXT_CSD *ExtCsd;\r
650 EMMC_HC_SLOT_CAP Capability;\r
651 EMMC_PEIM_HC_SLOT *Slot;\r
652 UINT32 SecCount;\r
653 UINT32 GpSizeMult;\r
654\r
655 //\r
656 // Shadow this PEIM to run from memory\r
657 //\r
658 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
659 return EFI_SUCCESS;\r
660 }\r
661\r
662 //\r
663 // locate Emmc host controller PPI\r
664 //\r
665 Status = PeiServicesLocatePpi (\r
666 &gEdkiiPeiSdMmcHostControllerPpiGuid,\r
667 0,\r
668 NULL,\r
669 (VOID **) &SdMmcHcPpi\r
670 );\r
671 if (EFI_ERROR (Status)) {\r
672 return EFI_DEVICE_ERROR;\r
673 }\r
674\r
675 Controller = 0;\r
676 MmioBase = NULL;\r
677 while (TRUE) {\r
678 Status = SdMmcHcPpi->GetSdMmcHcMmioBar (SdMmcHcPpi, Controller, &MmioBase, &BarNum);\r
679 //\r
680 // When status is error, meant no controller is found\r
681 //\r
682 if (EFI_ERROR (Status)) {\r
683 break;\r
684 }\r
685\r
686 if (BarNum == 0) {\r
687 Controller++;\r
688 continue;\r
689 }\r
690\r
691 Private = AllocateCopyPool (sizeof (EMMC_PEIM_HC_PRIVATE_DATA), &gEmmcHcPrivateTemplate);\r
692 if (Private == NULL) {\r
693 Status = EFI_OUT_OF_RESOURCES;\r
694 break;\r
695 }\r
696 Private->BlkIoPpiList.Ppi = (VOID*)&Private->BlkIoPpi;\r
697 Private->BlkIo2PpiList.Ppi = (VOID*)&Private->BlkIo2Ppi;\r
698 //\r
699 // Initialize the memory pool which will be used in all transactions.\r
700 //\r
701 Status = EmmcPeimInitMemPool (Private);\r
702 if (EFI_ERROR (Status)) {\r
703 Status = EFI_OUT_OF_RESOURCES;\r
704 break;\r
705 }\r
706\r
707 for (Index = 0; Index < BarNum; Index++) {\r
708 Status = EmmcPeimHcGetCapability (MmioBase[Index], &Capability);\r
709 if (EFI_ERROR (Status)) {\r
710 continue;\r
711 }\r
712 if (Capability.SlotType != 0x1) {\r
713 DEBUG ((EFI_D_INFO, "The slot at 0x%x is not embedded slot type\n", MmioBase[Index]));\r
714 Status = EFI_UNSUPPORTED;\r
715 continue;\r
716 }\r
717\r
718 Status = EmmcPeimHcReset (MmioBase[Index]);\r
719 if (EFI_ERROR (Status)) {\r
720 continue;\r
721 }\r
722 Status = EmmcPeimHcCardDetect (MmioBase[Index]);\r
723 if (EFI_ERROR (Status)) {\r
724 continue;\r
725 }\r
726 Status = EmmcPeimHcInitHost (MmioBase[Index]);\r
727 if (EFI_ERROR (Status)) {\r
728 continue;\r
729 }\r
730\r
731 SlotNum = Private->SlotNum;\r
732 Slot = &Private->Slot[SlotNum];\r
733 CopyMem (Slot, &gEmmcHcSlotTemplate, sizeof (EMMC_PEIM_HC_SLOT));\r
734 Slot->Private = Private;\r
735 Slot->EmmcHcBase = MmioBase[Index];\r
736 CopyMem (&Slot->Capability, &Capability, sizeof (Capability));\r
737\r
738 Status = EmmcPeimIdentification (Slot);\r
739 if (EFI_ERROR (Status)) {\r
740 continue;\r
741 }\r
742\r
743 ExtCsd = &Slot->ExtCsd;\r
744 if (ExtCsd->ExtCsdRev < 5) {\r
745 DEBUG ((EFI_D_ERROR, "The EMMC device version is too low, we don't support!!!\n"));\r
746 Status = EFI_UNSUPPORTED;\r
747 continue;\r
748 }\r
749 if ((ExtCsd->PartitioningSupport & BIT0) != BIT0) {\r
750 DEBUG ((EFI_D_ERROR, "The EMMC device doesn't support Partition Feature!!!\n"));\r
751 Status = EFI_UNSUPPORTED;\r
752 continue;\r
753 }\r
754\r
755 for (PartitionIndex = 0; PartitionIndex < EMMC_PEIM_MAX_PARTITIONS; PartitionIndex++) {\r
756 switch (PartitionIndex) {\r
757 case EmmcPartitionUserData:\r
758 SecCount = *(UINT32*)&ExtCsd->SecCount;\r
759 Capacity = MultU64x32 ((UINT64)SecCount, 0x200);\r
760 break;\r
761 case EmmcPartitionBoot1:\r
762 case EmmcPartitionBoot2:\r
763 Capacity = ExtCsd->BootSizeMult * SIZE_128KB;\r
764 break;\r
765 case EmmcPartitionRPMB:\r
766 Capacity = ExtCsd->RpmbSizeMult * SIZE_128KB;\r
767 break;\r
768 case EmmcPartitionGP1:\r
769 GpSizeMult = (ExtCsd->GpSizeMult[0] | (ExtCsd->GpSizeMult[1] << 8) | (ExtCsd->GpSizeMult[2] << 16));\r
770 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
771 break;\r
772 case EmmcPartitionGP2:\r
773 GpSizeMult = (ExtCsd->GpSizeMult[3] | (ExtCsd->GpSizeMult[4] << 8) | (ExtCsd->GpSizeMult[5] << 16));\r
774 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
775 break;\r
776 case EmmcPartitionGP3:\r
777 GpSizeMult = (ExtCsd->GpSizeMult[6] | (ExtCsd->GpSizeMult[7] << 8) | (ExtCsd->GpSizeMult[8] << 16));\r
778 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
779 break;\r
780 case EmmcPartitionGP4:\r
781 GpSizeMult = (ExtCsd->GpSizeMult[9] | (ExtCsd->GpSizeMult[10] << 8) | (ExtCsd->GpSizeMult[11] << 16));\r
782 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
783 break;\r
784 default:\r
785 ASSERT (FALSE);\r
786 continue;\r
787 }\r
788\r
789 MediaNum = Slot->MediaNum;\r
790 if (Capacity != 0) {\r
791 Slot->Media[MediaNum].LastBlock = DivU64x32 (Capacity, Slot->Media[MediaNum].BlockSize) - 1;\r
792 Slot->PartitionType[MediaNum] = PartitionIndex;\r
793 Private->TotalBlkIoDevices++;\r
794 Slot->MediaNum++;\r
795 }\r
796 }\r
797 Private->SlotNum++;\r
798 }\r
799 Controller++;\r
800\r
801 if (!EFI_ERROR (Status)) {\r
802 PeiServicesInstallPpi (&Private->BlkIoPpiList);\r
803 }\r
804 }\r
805\r
806 return EFI_SUCCESS;\r
807}\r