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