]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / SdBlockIoPei / SdBlockIoPei.c
CommitLineData
48555339
FT
1/** @file\r
2\r
77af8668 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 "SdBlockIoPei.h"\r
9\r
10//\r
11// Template for SD HC Slot Data.\r
12//\r
13SD_PEIM_HC_SLOT gSdHcSlotTemplate = {\r
14 SD_PEIM_SLOT_SIG, // Signature\r
15 { // Media\r
16 MSG_SD_DP,\r
17 FALSE,\r
18 TRUE,\r
19 FALSE,\r
20 0x200,\r
21 0\r
22 },\r
23 0, // SdHcBase\r
24 { // Capability\r
25 0,\r
26 },\r
27 { // Csd\r
28 0,\r
29 },\r
30 TRUE, // SectorAddressing\r
31 NULL // Private\r
32};\r
33\r
34//\r
35// Template for SD HC Private Data.\r
36//\r
37SD_PEIM_HC_PRIVATE_DATA gSdHcPrivateTemplate = {\r
38 SD_PEIM_SIG, // Signature\r
39 NULL, // Pool\r
40 { // BlkIoPpi\r
41 SdBlockIoPeimGetDeviceNo,\r
42 SdBlockIoPeimGetMediaInfo,\r
43 SdBlockIoPeimReadBlocks\r
44 },\r
45 { // BlkIo2Ppi\r
46 EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,\r
47 SdBlockIoPeimGetDeviceNo2,\r
48 SdBlockIoPeimGetMediaInfo2,\r
49 SdBlockIoPeimReadBlocks2\r
50 },\r
51 { // BlkIoPpiList\r
52 EFI_PEI_PPI_DESCRIPTOR_PPI,\r
53 &gEfiPeiVirtualBlockIoPpiGuid,\r
54 NULL\r
55 },\r
56 { // BlkIo2PpiList\r
57 EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,\r
58 &gEfiPeiVirtualBlockIo2PpiGuid,\r
59 NULL\r
60 },\r
77af8668
HW
61 {\r
62 (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
63 &gEfiEndOfPeiSignalPpiGuid,\r
64 SdBlockIoPeimEndOfPei\r
65 },\r
48555339
FT
66 { // Slot\r
67 {\r
68 0,\r
69 },\r
70 {\r
71 0,\r
72 },\r
73 {\r
74 0,\r
75 },\r
76 {\r
77 0,\r
78 },\r
79 {\r
80 0,\r
81 },\r
82 {\r
83 0,\r
84 }\r
85 },\r
86 0, // SlotNum\r
87 0 // TotalBlkIoDevices\r
88};\r
89/**\r
90 Gets the count of block I/O devices that one specific block driver detects.\r
91\r
92 This function is used for getting the count of block I/O devices that one\r
93 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
94 of all the detected ATAPI devices it detects during the enumeration process.\r
95 To the PEI legacy floppy driver, it returns the number of all the legacy\r
96 devices it finds during its enumeration process. If no device is detected,\r
97 then the function will return zero.\r
98\r
99 @param[in] PeiServices General-purpose services that are available\r
100 to every PEIM.\r
101 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI\r
102 instance.\r
103 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
104\r
105 @retval EFI_SUCCESS The operation performed successfully.\r
106\r
107**/\r
108EFI_STATUS\r
109EFIAPI\r
110SdBlockIoPeimGetDeviceNo (\r
111 IN EFI_PEI_SERVICES **PeiServices,\r
112 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
113 OUT UINTN *NumberBlockDevices\r
114 )\r
115{\r
116 SD_PEIM_HC_PRIVATE_DATA *Private;\r
117\r
118 Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
119 *NumberBlockDevices = Private->TotalBlkIoDevices;\r
120 return EFI_SUCCESS;\r
121}\r
122\r
123/**\r
124 Gets a block device's media information.\r
125\r
126 This function will provide the caller with the specified block device's media\r
127 information. If the media changes, calling this function will update the media\r
128 information accordingly.\r
129\r
130 @param[in] PeiServices General-purpose services that are available to every\r
131 PEIM\r
132 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
133 @param[in] DeviceIndex Specifies the block device to which the function wants\r
134 to talk. Because the driver that implements Block I/O\r
135 PPIs will manage multiple block devices, the PPIs that\r
136 want to talk to a single device must specify the\r
137 device index that was assigned during the enumeration\r
138 process. This index is a number from one to\r
139 NumberBlockDevices.\r
140 @param[out] MediaInfo The media information of the specified block media.\r
141 The caller is responsible for the ownership of this\r
142 data structure.\r
143\r
144 @par Note:\r
145 The MediaInfo structure describes an enumeration of possible block device\r
146 types. This enumeration exists because no device paths are actually passed\r
147 across interfaces that describe the type or class of hardware that is publishing\r
148 the block I/O interface. This enumeration will allow for policy decisions\r
149 in the Recovery PEIM, such as "Try to recover from legacy floppy first,\r
150 LS-120 second, CD-ROM third." If there are multiple partitions abstracted\r
151 by a given device type, they should be reported in ascending order; this\r
152 order also applies to nested partitions, such as legacy MBR, where the\r
153 outermost partitions would have precedence in the reporting order. The\r
154 same logic applies to systems such as IDE that have precedence relationships\r
155 like "Master/Slave" or "Primary/Secondary". The master device should be\r
156 reported first, the slave second.\r
157\r
158 @retval EFI_SUCCESS Media information about the specified block device\r
159 was obtained successfully.\r
160 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
161 error.\r
162\r
163**/\r
164EFI_STATUS\r
165EFIAPI\r
166SdBlockIoPeimGetMediaInfo (\r
167 IN EFI_PEI_SERVICES **PeiServices,\r
168 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
169 IN UINTN DeviceIndex,\r
170 OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo\r
171 )\r
172{\r
173 SD_PEIM_HC_PRIVATE_DATA *Private;\r
174\r
175 Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
176\r
177 if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {\r
178 return EFI_INVALID_PARAMETER;\r
179 }\r
180\r
181 MediaInfo->DeviceType = SD;\r
182 MediaInfo->MediaPresent = TRUE;\r
183 MediaInfo->LastBlock = (UINTN)Private->Slot[DeviceIndex - 1].Media.LastBlock;\r
184 MediaInfo->BlockSize = Private->Slot[DeviceIndex - 1].Media.BlockSize;\r
185\r
186 return EFI_SUCCESS;\r
187}\r
188\r
189/**\r
190 Reads the requested number of blocks from the specified block device.\r
191\r
192 The function reads the requested number of blocks from the device. All the\r
193 blocks are read, or an error is returned. If there is no media in the device,\r
194 the function returns EFI_NO_MEDIA.\r
195\r
196 @param[in] PeiServices General-purpose services that are available to\r
197 every PEIM.\r
198 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.\r
199 @param[in] DeviceIndex Specifies the block device to which the function wants\r
200 to talk. Because the driver that implements Block I/O\r
201 PPIs will manage multiple block devices, PPIs that\r
202 want to talk to a single device must specify the device\r
203 index that was assigned during the enumeration process.\r
204 This index is a number from one to NumberBlockDevices.\r
205 @param[in] StartLBA The starting logical block address (LBA) to read from\r
206 on the device\r
207 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
208 a multiple of the intrinsic block size of the device.\r
209 @param[out] Buffer A pointer to the destination buffer for the data.\r
210 The caller is responsible for the ownership of the\r
211 buffer.\r
212\r
213 @retval EFI_SUCCESS The data was read correctly from the device.\r
214 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
215 to perform the read operation.\r
216 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
217 valid, or the buffer is not properly aligned.\r
218 @retval EFI_NO_MEDIA There is no media in the device.\r
219 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
220 the intrinsic block size of the device.\r
221\r
222**/\r
223EFI_STATUS\r
224EFIAPI\r
225SdBlockIoPeimReadBlocks (\r
226 IN EFI_PEI_SERVICES **PeiServices,\r
227 IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,\r
228 IN UINTN DeviceIndex,\r
229 IN EFI_PEI_LBA StartLBA,\r
230 IN UINTN BufferSize,\r
231 OUT VOID *Buffer\r
232 )\r
233{\r
234 EFI_STATUS Status;\r
235 UINT32 BlockSize;\r
236 UINTN NumberOfBlocks;\r
237 SD_PEIM_HC_PRIVATE_DATA *Private;\r
238 UINTN Remaining;\r
239 UINT32 MaxBlock;\r
240\r
241 Status = EFI_SUCCESS;\r
242 Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);\r
243\r
244 //\r
245 // Check parameters\r
246 //\r
247 if (Buffer == NULL) {\r
248 return EFI_INVALID_PARAMETER;\r
249 }\r
250\r
251 if (BufferSize == 0) {\r
252 return EFI_SUCCESS;\r
253 }\r
254\r
255 if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {\r
256 return EFI_INVALID_PARAMETER;\r
257 }\r
258\r
259 BlockSize = Private->Slot[DeviceIndex - 1].Media.BlockSize;\r
260 if (BufferSize % BlockSize != 0) {\r
261 return EFI_BAD_BUFFER_SIZE;\r
262 }\r
263\r
264 if (StartLBA > Private->Slot[DeviceIndex - 1].Media.LastBlock) {\r
265 return EFI_INVALID_PARAMETER;\r
266 }\r
267\r
268 NumberOfBlocks = BufferSize / BlockSize;\r
269\r
270 //\r
271 // Start to execute data transfer. The max block number in single cmd is 65535 blocks.\r
272 //\r
273 Remaining = NumberOfBlocks;\r
274 MaxBlock = 0xFFFF;\r
275\r
276 while (Remaining > 0) {\r
277 if (Remaining <= MaxBlock) {\r
278 NumberOfBlocks = Remaining;\r
279 } else {\r
280 NumberOfBlocks = MaxBlock;\r
281 }\r
282\r
283 BufferSize = NumberOfBlocks * BlockSize;\r
284 if (NumberOfBlocks != 1) {\r
285 Status = SdPeimRwMultiBlocks (&Private->Slot[DeviceIndex - 1], StartLBA, BlockSize, Buffer, BufferSize, TRUE);\r
286 } else {\r
287 Status = SdPeimRwSingleBlock (&Private->Slot[DeviceIndex - 1], StartLBA, BlockSize, Buffer, BufferSize, TRUE);\r
288 }\r
289 if (EFI_ERROR (Status)) {\r
290 return Status;\r
291 }\r
292\r
293 StartLBA += NumberOfBlocks;\r
294 Buffer = (UINT8*)Buffer + BufferSize;\r
295 Remaining -= NumberOfBlocks;\r
296 }\r
297 return Status;\r
298}\r
299\r
300/**\r
301 Gets the count of block I/O devices that one specific block driver detects.\r
302\r
303 This function is used for getting the count of block I/O devices that one\r
304 specific block driver detects. To the PEI ATAPI driver, it returns the number\r
305 of all the detected ATAPI devices it detects during the enumeration process.\r
306 To the PEI legacy floppy driver, it returns the number of all the legacy\r
307 devices it finds during its enumeration process. If no device is detected,\r
308 then the function will return zero.\r
309\r
310 @param[in] PeiServices General-purpose services that are available\r
311 to every PEIM.\r
312 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI\r
313 instance.\r
314 @param[out] NumberBlockDevices The number of block I/O devices discovered.\r
315\r
316 @retval EFI_SUCCESS The operation performed successfully.\r
317\r
318**/\r
319EFI_STATUS\r
320EFIAPI\r
321SdBlockIoPeimGetDeviceNo2 (\r
322 IN EFI_PEI_SERVICES **PeiServices,\r
323 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
324 OUT UINTN *NumberBlockDevices\r
325 )\r
326{\r
327 SD_PEIM_HC_PRIVATE_DATA *Private;\r
328\r
329 Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
330 *NumberBlockDevices = Private->TotalBlkIoDevices;\r
331\r
332 return EFI_SUCCESS;\r
333}\r
334\r
335/**\r
336 Gets a block device's media information.\r
337\r
338 This function will provide the caller with the specified block device's media\r
339 information. If the media changes, calling this function will update the media\r
340 information accordingly.\r
341\r
342 @param[in] PeiServices General-purpose services that are available to every\r
343 PEIM\r
344 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
345 @param[in] DeviceIndex Specifies the block device to which the function wants\r
346 to talk. Because the driver that implements Block I/O\r
347 PPIs will manage multiple block devices, the PPIs that\r
348 want to talk to a single device must specify the\r
349 device index that was assigned during the enumeration\r
350 process. This index is a number from one to\r
351 NumberBlockDevices.\r
352 @param[out] MediaInfo The media information of the specified block media.\r
353 The caller is responsible for the ownership of this\r
354 data structure.\r
355\r
356 @par Note:\r
357 The MediaInfo structure describes an enumeration of possible block device\r
358 types. This enumeration exists because no device paths are actually passed\r
359 across interfaces that describe the type or class of hardware that is publishing\r
360 the block I/O interface. This enumeration will allow for policy decisions\r
361 in the Recovery PEIM, such as "Try to recover from legacy floppy first,\r
362 LS-120 second, CD-ROM third." If there are multiple partitions abstracted\r
363 by a given device type, they should be reported in ascending order; this\r
364 order also applies to nested partitions, such as legacy MBR, where the\r
365 outermost partitions would have precedence in the reporting order. The\r
366 same logic applies to systems such as IDE that have precedence relationships\r
367 like "Master/Slave" or "Primary/Secondary". The master device should be\r
368 reported first, the slave second.\r
369\r
370 @retval EFI_SUCCESS Media information about the specified block device\r
371 was obtained successfully.\r
372 @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware\r
373 error.\r
374\r
375**/\r
376EFI_STATUS\r
377EFIAPI\r
378SdBlockIoPeimGetMediaInfo2 (\r
379 IN EFI_PEI_SERVICES **PeiServices,\r
380 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
381 IN UINTN DeviceIndex,\r
382 OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo\r
383 )\r
384{\r
385 EFI_STATUS Status;\r
386 SD_PEIM_HC_PRIVATE_DATA *Private;\r
387 EFI_PEI_BLOCK_IO_MEDIA Media;\r
388\r
389 Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
390\r
391 Status = SdBlockIoPeimGetMediaInfo (\r
392 PeiServices,\r
393 &Private->BlkIoPpi,\r
394 DeviceIndex,\r
395 &Media\r
396 );\r
397 if (EFI_ERROR (Status)) {\r
398 return Status;\r
399 }\r
400\r
401 CopyMem (MediaInfo, &(Private->Slot[DeviceIndex - 1].Media), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));\r
402 return EFI_SUCCESS;\r
403}\r
404\r
405/**\r
406 Reads the requested number of blocks from the specified block device.\r
407\r
408 The function reads the requested number of blocks from the device. All the\r
409 blocks are read, or an error is returned. If there is no media in the device,\r
410 the function returns EFI_NO_MEDIA.\r
411\r
412 @param[in] PeiServices General-purpose services that are available to\r
413 every PEIM.\r
414 @param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO2_PPI instance.\r
415 @param[in] DeviceIndex Specifies the block device to which the function wants\r
416 to talk. Because the driver that implements Block I/O\r
417 PPIs will manage multiple block devices, PPIs that\r
418 want to talk to a single device must specify the device\r
419 index that was assigned during the enumeration process.\r
420 This index is a number from one to NumberBlockDevices.\r
421 @param[in] StartLBA The starting logical block address (LBA) to read from\r
422 on the device\r
423 @param[in] BufferSize The size of the Buffer in bytes. This number must be\r
424 a multiple of the intrinsic block size of the device.\r
425 @param[out] Buffer A pointer to the destination buffer for the data.\r
426 The caller is responsible for the ownership of the\r
427 buffer.\r
428\r
429 @retval EFI_SUCCESS The data was read correctly from the device.\r
430 @retval EFI_DEVICE_ERROR The device reported an error while attempting\r
431 to perform the read operation.\r
432 @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not\r
433 valid, or the buffer is not properly aligned.\r
434 @retval EFI_NO_MEDIA There is no media in the device.\r
435 @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of\r
436 the intrinsic block size of the device.\r
437\r
438**/\r
439EFI_STATUS\r
440EFIAPI\r
441SdBlockIoPeimReadBlocks2 (\r
442 IN EFI_PEI_SERVICES **PeiServices,\r
443 IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,\r
444 IN UINTN DeviceIndex,\r
445 IN EFI_PEI_LBA StartLBA,\r
446 IN UINTN BufferSize,\r
447 OUT VOID *Buffer\r
448 )\r
449{\r
450 EFI_STATUS Status;\r
451 SD_PEIM_HC_PRIVATE_DATA *Private;\r
452\r
453 Status = EFI_SUCCESS;\r
454 Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);\r
455\r
456 Status = SdBlockIoPeimReadBlocks (\r
457 PeiServices,\r
458 &Private->BlkIoPpi,\r
459 DeviceIndex,\r
460 StartLBA,\r
461 BufferSize,\r
462 Buffer\r
463 );\r
464 return Status;\r
465}\r
466\r
77af8668
HW
467/**\r
468 One notified function to cleanup the allocated DMA buffers at the end of PEI.\r
469\r
470 @param[in] PeiServices Pointer to PEI Services Table.\r
471 @param[in] NotifyDescriptor Pointer to the descriptor for the Notification\r
472 event that caused this function to execute.\r
473 @param[in] Ppi Pointer to the PPI data associated with this function.\r
474\r
475 @retval EFI_SUCCESS The function completes successfully\r
476\r
477**/\r
478EFI_STATUS\r
479EFIAPI\r
480SdBlockIoPeimEndOfPei (\r
481 IN EFI_PEI_SERVICES **PeiServices,\r
482 IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,\r
483 IN VOID *Ppi\r
484 )\r
485{\r
486 SD_PEIM_HC_PRIVATE_DATA *Private;\r
487\r
488 Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS_NOTIFY (NotifyDescriptor);\r
489\r
490 if ((Private->Pool != NULL) && (Private->Pool->Head != NULL)) {\r
491 SdPeimFreeMemPool (Private->Pool);\r
492 }\r
493\r
494 return EFI_SUCCESS;\r
495}\r
496\r
48555339
FT
497/**\r
498 The user code starts with this function.\r
499\r
500 @param FileHandle Handle of the file being invoked.\r
501 @param PeiServices Describes the list of possible PEI Services.\r
502\r
503 @retval EFI_SUCCESS The driver is successfully initialized.\r
504 @retval Others Can't initialize the driver.\r
505\r
506**/\r
507EFI_STATUS\r
508EFIAPI\r
509InitializeSdBlockIoPeim (\r
510 IN EFI_PEI_FILE_HANDLE FileHandle,\r
511 IN CONST EFI_PEI_SERVICES **PeiServices\r
512 )\r
513{\r
514 EFI_STATUS Status;\r
515 SD_PEIM_HC_PRIVATE_DATA *Private;\r
516 EDKII_SD_MMC_HOST_CONTROLLER_PPI *SdMmcHcPpi;\r
517 UINT32 Index;\r
518 UINTN *MmioBase;\r
519 UINT8 BarNum;\r
520 UINT8 SlotNum;\r
521 UINT8 Controller;\r
522 UINT64 Capacity;\r
523 SD_HC_SLOT_CAP Capability;\r
524 SD_PEIM_HC_SLOT *Slot;\r
525 SD_CSD *Csd;\r
526 SD_CSD2 *Csd2;\r
527 UINT32 CSize;\r
528 UINT32 CSizeMul;\r
529 UINT32 ReadBlLen;\r
530\r
531 //\r
532 // Shadow this PEIM to run from memory\r
533 //\r
534 if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {\r
535 return EFI_SUCCESS;\r
536 }\r
537\r
538 //\r
539 // locate Sd host controller PPI\r
540 //\r
541 Status = PeiServicesLocatePpi (\r
542 &gEdkiiPeiSdMmcHostControllerPpiGuid,\r
543 0,\r
544 NULL,\r
545 (VOID **) &SdMmcHcPpi\r
546 );\r
547 if (EFI_ERROR (Status)) {\r
548 return EFI_DEVICE_ERROR;\r
549 }\r
550\r
77af8668
HW
551 IoMmuInit ();\r
552\r
48555339
FT
553 Controller = 0;\r
554 MmioBase = NULL;\r
555 while (TRUE) {\r
556 Status = SdMmcHcPpi->GetSdMmcHcMmioBar (SdMmcHcPpi, Controller, &MmioBase, &BarNum);\r
557 //\r
558 // When status is error, meant no controller is found\r
559 //\r
560 if (EFI_ERROR (Status)) {\r
561 break;\r
562 }\r
563\r
564 if (BarNum == 0) {\r
565 Controller++;\r
566 continue;\r
567 }\r
568\r
569 Private = AllocateCopyPool (sizeof (SD_PEIM_HC_PRIVATE_DATA), &gSdHcPrivateTemplate);\r
570 if (Private == NULL) {\r
571 Status = EFI_OUT_OF_RESOURCES;\r
572 break;\r
573 }\r
574 Private->BlkIoPpiList.Ppi = (VOID*)&Private->BlkIoPpi;\r
575 Private->BlkIo2PpiList.Ppi = (VOID*)&Private->BlkIo2Ppi;\r
576 //\r
577 // Initialize the memory pool which will be used in all transactions.\r
578 //\r
579 Status = SdPeimInitMemPool (Private);\r
580 if (EFI_ERROR (Status)) {\r
581 Status = EFI_OUT_OF_RESOURCES;\r
582 break;\r
583 }\r
584\r
585 for (Index = 0; Index < BarNum; Index++) {\r
586 Status = SdPeimHcGetCapability (MmioBase[Index], &Capability);\r
587 if (EFI_ERROR (Status)) {\r
588 continue;\r
589 }\r
590 if (Capability.SlotType != 0x1) {\r
591 DEBUG ((EFI_D_INFO, "The slot at 0x%x is not embedded slot type\n", MmioBase[Index]));\r
592 Status = EFI_UNSUPPORTED;\r
593 continue;\r
594 }\r
595\r
596 Status = SdPeimHcReset (MmioBase[Index]);\r
597 if (EFI_ERROR (Status)) {\r
598 continue;\r
599 }\r
600 Status = SdPeimHcCardDetect (MmioBase[Index]);\r
601 if (EFI_ERROR (Status)) {\r
602 continue;\r
603 }\r
604 Status = SdPeimHcInitHost (MmioBase[Index]);\r
605 if (EFI_ERROR (Status)) {\r
606 continue;\r
607 }\r
608\r
609 SlotNum = Private->SlotNum;\r
610 Slot = &Private->Slot[SlotNum];\r
611 CopyMem (Slot, &gSdHcSlotTemplate, sizeof (SD_PEIM_HC_SLOT));\r
612 Slot->Private = Private;\r
613 Slot->SdHcBase = MmioBase[Index];\r
614 CopyMem (&Slot->Capability, &Capability, sizeof (Capability));\r
615\r
616 Status = SdPeimIdentification (Slot);\r
617 if (EFI_ERROR (Status)) {\r
618 continue;\r
619 }\r
620\r
621 Csd = &Slot->Csd;\r
622 if (Csd->CsdStructure == 0) {\r
623 Slot->SectorAddressing = FALSE;\r
624 CSize = (Csd->CSizeHigh << 2 | Csd->CSizeLow) + 1;\r
625 CSizeMul = (1 << (Csd->CSizeMul + 2));\r
626 ReadBlLen = (1 << (Csd->ReadBlLen));\r
627 Capacity = MultU64x32 (MultU64x32 ((UINT64)CSize, CSizeMul), ReadBlLen);\r
628 } else {\r
629 Slot->SectorAddressing = TRUE;\r
630 Csd2 = (SD_CSD2*)(VOID*)Csd;\r
631 CSize = (Csd2->CSizeHigh << 16 | Csd2->CSizeLow) + 1;\r
632 Capacity = MultU64x32 ((UINT64)CSize, SIZE_512KB);\r
633 }\r
634\r
635 Slot->Media.LastBlock = DivU64x32 (Capacity, Slot->Media.BlockSize) - 1;\r
636\r
637 Private->TotalBlkIoDevices++;\r
638 Private->SlotNum++;\r
639 }\r
640\r
641 Controller++;\r
642 if (!EFI_ERROR (Status)) {\r
643 PeiServicesInstallPpi (&Private->BlkIoPpiList);\r
77af8668
HW
644 PeiServicesNotifyPpi (&Private->EndOfPeiNotifyList);\r
645 } else {\r
646 if (Private->Pool->Head != NULL) {\r
647 SdPeimFreeMemPool (Private->Pool);\r
648 }\r
48555339
FT
649 }\r
650 }\r
651\r
652 return EFI_SUCCESS;\r
653}\r