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