2 The EmmcDxe driver is used to manage the EMMC device.
4 It produces BlockIo, BlockIo2 and StorageSecurity protocols to allow upper layer
5 access the EMMC device.
7 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
8 SPDX-License-Identifier: BSD-2-Clause-Patent
15 // EmmcDxe Driver Binding Protocol Instance
17 EFI_DRIVER_BINDING_PROTOCOL gEmmcDxeDriverBinding
= {
18 EmmcDxeDriverBindingSupported
,
19 EmmcDxeDriverBindingStart
,
20 EmmcDxeDriverBindingStop
,
27 // Template for Emmc Partitions.
29 EMMC_PARTITION mEmmcPartitionTemplate
= {
30 EMMC_PARTITION_SIGNATURE
, // Signature
32 EmmcPartitionUnknown
, // PartitionType
36 EFI_BLOCK_IO_PROTOCOL_REVISION
,
52 FALSE
, // RemovableMedia
54 FALSE
, // LogicPartition
56 FALSE
, // WritingCache
62 EmmcSecurityProtocolIn
,
63 EmmcSecurityProtocolOut
66 EFI_ERASE_BLOCK_PROTOCOL_REVISION
,
71 EFI_DISK_INFO_SD_MMC_INTERFACE_GUID
,
74 EmmcDiskInfoSenseData
,
85 Decode and print EMMC CSD Register content.
87 @param[in] Csd Pointer to EMMC_CSD data structure.
89 @retval EFI_SUCCESS The function completed successfully
96 DEBUG((DEBUG_INFO
, "== Dump Emmc Csd Register==\n"));
97 DEBUG((DEBUG_INFO
, " CSD structure 0x%x\n", Csd
->CsdStructure
));
98 DEBUG((DEBUG_INFO
, " System specification version 0x%x\n", Csd
->SpecVers
));
99 DEBUG((DEBUG_INFO
, " Data read access-time 1 0x%x\n", Csd
->Taac
));
100 DEBUG((DEBUG_INFO
, " Data read access-time 2 0x%x\n", Csd
->Nsac
));
101 DEBUG((DEBUG_INFO
, " Max. bus clock frequency 0x%x\n", Csd
->TranSpeed
));
102 DEBUG((DEBUG_INFO
, " Device command classes 0x%x\n", Csd
->Ccc
));
103 DEBUG((DEBUG_INFO
, " Max. read data block length 0x%x\n", Csd
->ReadBlLen
));
104 DEBUG((DEBUG_INFO
, " Partial blocks for read allowed 0x%x\n", Csd
->ReadBlPartial
));
105 DEBUG((DEBUG_INFO
, " Write block misalignment 0x%x\n", Csd
->WriteBlkMisalign
));
106 DEBUG((DEBUG_INFO
, " Read block misalignment 0x%x\n", Csd
->ReadBlkMisalign
));
107 DEBUG((DEBUG_INFO
, " DSR implemented 0x%x\n", Csd
->DsrImp
));
108 DEBUG((DEBUG_INFO
, " Device size 0x%x\n", Csd
->CSizeLow
| (Csd
->CSizeHigh
<< 2)));
109 DEBUG((DEBUG_INFO
, " Max. read current @ VDD min 0x%x\n", Csd
->VddRCurrMin
));
110 DEBUG((DEBUG_INFO
, " Max. read current @ VDD max 0x%x\n", Csd
->VddRCurrMax
));
111 DEBUG((DEBUG_INFO
, " Max. write current @ VDD min 0x%x\n", Csd
->VddWCurrMin
));
112 DEBUG((DEBUG_INFO
, " Max. write current @ VDD max 0x%x\n", Csd
->VddWCurrMax
));
113 DEBUG((DEBUG_INFO
, " Device size multiplier 0x%x\n", Csd
->CSizeMult
));
114 DEBUG((DEBUG_INFO
, " Erase group size 0x%x\n", Csd
->EraseGrpSize
));
115 DEBUG((DEBUG_INFO
, " Erase group size multiplier 0x%x\n", Csd
->EraseGrpMult
));
116 DEBUG((DEBUG_INFO
, " Write protect group size 0x%x\n", Csd
->WpGrpSize
));
117 DEBUG((DEBUG_INFO
, " Write protect group enable 0x%x\n", Csd
->WpGrpEnable
));
118 DEBUG((DEBUG_INFO
, " Manufacturer default ECC 0x%x\n", Csd
->DefaultEcc
));
119 DEBUG((DEBUG_INFO
, " Write speed factor 0x%x\n", Csd
->R2WFactor
));
120 DEBUG((DEBUG_INFO
, " Max. write data block length 0x%x\n", Csd
->WriteBlLen
));
121 DEBUG((DEBUG_INFO
, " Partial blocks for write allowed 0x%x\n", Csd
->WriteBlPartial
));
122 DEBUG((DEBUG_INFO
, " Content protection application 0x%x\n", Csd
->ContentProtApp
));
123 DEBUG((DEBUG_INFO
, " File format group 0x%x\n", Csd
->FileFormatGrp
));
124 DEBUG((DEBUG_INFO
, " Copy flag (OTP) 0x%x\n", Csd
->Copy
));
125 DEBUG((DEBUG_INFO
, " Permanent write protection 0x%x\n", Csd
->PermWriteProtect
));
126 DEBUG((DEBUG_INFO
, " Temporary write protection 0x%x\n", Csd
->TmpWriteProtect
));
127 DEBUG((DEBUG_INFO
, " File format 0x%x\n", Csd
->FileFormat
));
128 DEBUG((DEBUG_INFO
, " ECC code 0x%x\n", Csd
->Ecc
));
134 Decode and print EMMC EXT_CSD Register content.
136 @param[in] ExtCsd Pointer to the EMMC_EXT_CSD data structure.
138 @retval EFI_SUCCESS The function completed successfully
142 IN EMMC_EXT_CSD
*ExtCsd
145 DEBUG((DEBUG_INFO
, "==Dump Emmc ExtCsd Register==\n"));
146 DEBUG((DEBUG_INFO
, " Supported Command Sets 0x%x\n", ExtCsd
->CmdSet
));
147 DEBUG((DEBUG_INFO
, " HPI features 0x%x\n", ExtCsd
->HpiFeatures
));
148 DEBUG((DEBUG_INFO
, " Background operations support 0x%x\n", ExtCsd
->BkOpsSupport
));
149 DEBUG((DEBUG_INFO
, " Background operations status 0x%x\n", ExtCsd
->BkopsStatus
));
150 DEBUG((DEBUG_INFO
, " Number of correctly programmed sectors 0x%x\n", *((UINT32
*)&ExtCsd
->CorrectlyPrgSectorsNum
[0])));
151 DEBUG((DEBUG_INFO
, " Initialization time after partitioning 0x%x\n", ExtCsd
->IniTimeoutAp
));
152 DEBUG((DEBUG_INFO
, " TRIM Multiplier 0x%x\n", ExtCsd
->TrimMult
));
153 DEBUG((DEBUG_INFO
, " Secure Feature support 0x%x\n", ExtCsd
->SecFeatureSupport
));
154 DEBUG((DEBUG_INFO
, " Secure Erase Multiplier 0x%x\n", ExtCsd
->SecEraseMult
));
155 DEBUG((DEBUG_INFO
, " Secure TRIM Multiplier 0x%x\n", ExtCsd
->SecTrimMult
));
156 DEBUG((DEBUG_INFO
, " Boot information 0x%x\n", ExtCsd
->BootInfo
));
157 DEBUG((DEBUG_INFO
, " Boot partition size 0x%x\n", ExtCsd
->BootSizeMult
));
158 DEBUG((DEBUG_INFO
, " Access size 0x%x\n", ExtCsd
->AccSize
));
159 DEBUG((DEBUG_INFO
, " High-capacity erase unit size 0x%x\n", ExtCsd
->HcEraseGrpSize
));
160 DEBUG((DEBUG_INFO
, " High-capacity erase timeout 0x%x\n", ExtCsd
->EraseTimeoutMult
));
161 DEBUG((DEBUG_INFO
, " Reliable write sector count 0x%x\n", ExtCsd
->RelWrSecC
));
162 DEBUG((DEBUG_INFO
, " High-capacity write protect group size 0x%x\n", ExtCsd
->HcWpGrpSize
));
163 DEBUG((DEBUG_INFO
, " Sleep/awake timeout 0x%x\n", ExtCsd
->SATimeout
));
164 DEBUG((DEBUG_INFO
, " Sector Count 0x%x\n", *((UINT32
*)&ExtCsd
->SecCount
[0])));
165 DEBUG((DEBUG_INFO
, " Partition switching timing 0x%x\n", ExtCsd
->PartitionSwitchTime
));
166 DEBUG((DEBUG_INFO
, " Out-of-interrupt busy timing 0x%x\n", ExtCsd
->OutOfInterruptTime
));
167 DEBUG((DEBUG_INFO
, " I/O Driver Strength 0x%x\n", ExtCsd
->DriverStrength
));
168 DEBUG((DEBUG_INFO
, " Device type 0x%x\n", ExtCsd
->DeviceType
));
169 DEBUG((DEBUG_INFO
, " CSD STRUCTURE 0x%x\n", ExtCsd
->CsdStructure
));
170 DEBUG((DEBUG_INFO
, " Extended CSD revision 0x%x\n", ExtCsd
->ExtCsdRev
));
171 DEBUG((DEBUG_INFO
, " Command set 0x%x\n", ExtCsd
->CmdSet
));
172 DEBUG((DEBUG_INFO
, " Command set revision 0x%x\n", ExtCsd
->CmdSetRev
));
173 DEBUG((DEBUG_INFO
, " Power class 0x%x\n", ExtCsd
->PowerClass
));
174 DEBUG((DEBUG_INFO
, " High-speed interface timing 0x%x\n", ExtCsd
->HsTiming
));
175 DEBUG((DEBUG_INFO
, " Bus width mode 0x%x\n", ExtCsd
->BusWidth
));
176 DEBUG((DEBUG_INFO
, " Erased memory content 0x%x\n", ExtCsd
->ErasedMemCont
));
177 DEBUG((DEBUG_INFO
, " Partition configuration 0x%x\n", ExtCsd
->PartitionConfig
));
178 DEBUG((DEBUG_INFO
, " Boot config protection 0x%x\n", ExtCsd
->BootConfigProt
));
179 DEBUG((DEBUG_INFO
, " Boot bus Conditions 0x%x\n", ExtCsd
->BootBusConditions
));
180 DEBUG((DEBUG_INFO
, " High-density erase group definition 0x%x\n", ExtCsd
->EraseGroupDef
));
181 DEBUG((DEBUG_INFO
, " Boot write protection status register 0x%x\n", ExtCsd
->BootWpStatus
));
182 DEBUG((DEBUG_INFO
, " Boot area write protection register 0x%x\n", ExtCsd
->BootWp
));
183 DEBUG((DEBUG_INFO
, " User area write protection register 0x%x\n", ExtCsd
->UserWp
));
184 DEBUG((DEBUG_INFO
, " FW configuration 0x%x\n", ExtCsd
->FwConfig
));
185 DEBUG((DEBUG_INFO
, " RPMB Size 0x%x\n", ExtCsd
->RpmbSizeMult
));
186 DEBUG((DEBUG_INFO
, " H/W reset function 0x%x\n", ExtCsd
->RstFunction
));
187 DEBUG((DEBUG_INFO
, " Partitioning Support 0x%x\n", ExtCsd
->PartitioningSupport
));
188 DEBUG((DEBUG_INFO
, " Max Enhanced Area Size 0x%02x%02x%02x\n", \
189 ExtCsd
->MaxEnhSizeMult
[2], ExtCsd
->MaxEnhSizeMult
[1], ExtCsd
->MaxEnhSizeMult
[0]));
190 DEBUG((DEBUG_INFO
, " Partitions attribute 0x%x\n", ExtCsd
->PartitionsAttribute
));
191 DEBUG((DEBUG_INFO
, " Partitioning Setting 0x%x\n", ExtCsd
->PartitionSettingCompleted
));
192 DEBUG((DEBUG_INFO
, " General Purpose Partition 1 Size 0x%02x%02x%02x\n", \
193 ExtCsd
->GpSizeMult
[2], ExtCsd
->GpSizeMult
[1], ExtCsd
->GpSizeMult
[0]));
194 DEBUG((DEBUG_INFO
, " General Purpose Partition 2 Size 0x%02x%02x%02x\n", \
195 ExtCsd
->GpSizeMult
[5], ExtCsd
->GpSizeMult
[4], ExtCsd
->GpSizeMult
[3]));
196 DEBUG((DEBUG_INFO
, " General Purpose Partition 3 Size 0x%02x%02x%02x\n", \
197 ExtCsd
->GpSizeMult
[8], ExtCsd
->GpSizeMult
[7], ExtCsd
->GpSizeMult
[6]));
198 DEBUG((DEBUG_INFO
, " General Purpose Partition 4 Size 0x%02x%02x%02x\n", \
199 ExtCsd
->GpSizeMult
[11], ExtCsd
->GpSizeMult
[10], ExtCsd
->GpSizeMult
[9]));
200 DEBUG((DEBUG_INFO
, " Enhanced User Data Area Size 0x%02x%02x%02x\n", \
201 ExtCsd
->EnhSizeMult
[2], ExtCsd
->EnhSizeMult
[1], ExtCsd
->EnhSizeMult
[0]));
202 DEBUG((DEBUG_INFO
, " Enhanced User Data Start Address 0x%x\n", *((UINT32
*)&ExtCsd
->EnhStartAddr
[0])));
203 DEBUG((DEBUG_INFO
, " Bad Block Management mode 0x%x\n", ExtCsd
->SecBadBlkMgmnt
));
204 DEBUG((DEBUG_INFO
, " Native sector size 0x%x\n", ExtCsd
->NativeSectorSize
));
205 DEBUG((DEBUG_INFO
, " Sector size emulation 0x%x\n", ExtCsd
->UseNativeSector
));
206 DEBUG((DEBUG_INFO
, " Sector size 0x%x\n", ExtCsd
->DataSectorSize
));
212 Get EMMC device model name.
214 @param[in, out] Device The pointer to the EMMC_DEVICE data structure.
215 @param[in] Cid Pointer to EMMC_CID data structure.
217 @retval EFI_SUCCESS The function completed successfully
222 IN OUT EMMC_DEVICE
*Device
,
226 CHAR8 String
[EMMC_MODEL_NAME_MAX_LEN
];
228 ZeroMem (String
, sizeof (String
));
229 CopyMem (String
, &Cid
->OemId
, sizeof (Cid
->OemId
));
230 String
[sizeof (Cid
->OemId
)] = ' ';
231 CopyMem (String
+ sizeof (Cid
->OemId
) + 1, Cid
->ProductName
, sizeof (Cid
->ProductName
));
232 String
[sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
)] = ' ';
233 CopyMem (String
+ sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
) + 1, Cid
->ProductSerialNumber
, sizeof (Cid
->ProductSerialNumber
));
235 AsciiStrToUnicodeStrS (String
, Device
->ModelName
, sizeof (Device
->ModelName
) / sizeof (Device
->ModelName
[0]));
241 Discover all partitions in the EMMC device.
243 @param[in] Device The pointer to the EMMC_DEVICE data structure.
245 @retval EFI_SUCCESS All the partitions in the device are successfully enumerated.
246 @return Others Some error occurs when enumerating the partitions.
250 DiscoverAllPartitions (
251 IN EMMC_DEVICE
*Device
255 EMMC_PARTITION
*Partition
;
258 EMMC_EXT_CSD
*ExtCsd
;
268 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
269 if (EFI_ERROR (Status
)) {
273 // Deselect the device to force it enter stby mode before getting CSD
275 // Note here we don't judge return status as some EMMC devices return
276 // error but the state has been stby.
278 EmmcSelect (Device
, 0);
280 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
281 if (EFI_ERROR (Status
)) {
286 Status
= EmmcGetCsd (Device
, Slot
+ 1, Csd
);
287 if (EFI_ERROR (Status
)) {
292 if ((Csd
->CSizeLow
| Csd
->CSizeHigh
<< 2) == 0xFFF) {
293 Device
->SectorAddressing
= TRUE
;
295 Device
->SectorAddressing
= FALSE
;
299 Status
= EmmcGetCid (Device
, Slot
+ 1, Cid
);
300 if (EFI_ERROR (Status
)) {
304 Status
= EmmcSelect (Device
, Slot
+ 1);
305 if (EFI_ERROR (Status
)) {
309 ExtCsd
= &Device
->ExtCsd
;
310 Status
= EmmcGetExtCsd (Device
, ExtCsd
);
311 if (EFI_ERROR (Status
)) {
316 if (ExtCsd
->ExtCsdRev
< 5) {
317 DEBUG ((EFI_D_ERROR
, "The EMMC device version is too low, we don't support!!!\n"));
318 return EFI_UNSUPPORTED
;
321 if ((ExtCsd
->PartitioningSupport
& BIT0
) != BIT0
) {
322 DEBUG ((EFI_D_ERROR
, "The EMMC device doesn't support Partition Feature!!!\n"));
323 return EFI_UNSUPPORTED
;
326 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
327 Partition
= &Device
->Partition
[Index
];
328 CopyMem (Partition
, &mEmmcPartitionTemplate
, sizeof (EMMC_PARTITION
));
329 Partition
->Device
= Device
;
330 InitializeListHead (&Partition
->Queue
);
331 Partition
->BlockIo
.Media
= &Partition
->BlockMedia
;
332 Partition
->BlockIo2
.Media
= &Partition
->BlockMedia
;
333 Partition
->PartitionType
= Index
;
334 Partition
->BlockMedia
.IoAlign
= Device
->Private
->PassThru
->IoAlign
;
335 Partition
->BlockMedia
.BlockSize
= 0x200;
336 Partition
->BlockMedia
.LastBlock
= 0x00;
337 Partition
->BlockMedia
.RemovableMedia
= FALSE
;
338 Partition
->BlockMedia
.MediaPresent
= TRUE
;
339 Partition
->BlockMedia
.LogicalPartition
= FALSE
;
342 case EmmcPartitionUserData
:
343 SecCount
= *(UINT32
*)&ExtCsd
->SecCount
;
344 Capacity
= MultU64x32 ((UINT64
) SecCount
, 0x200);
346 case EmmcPartitionBoot1
:
347 case EmmcPartitionBoot2
:
348 Capacity
= ExtCsd
->BootSizeMult
* SIZE_128KB
;
350 case EmmcPartitionRPMB
:
351 Capacity
= ExtCsd
->RpmbSizeMult
* SIZE_128KB
;
353 case EmmcPartitionGP1
:
354 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[0] | (ExtCsd
->GpSizeMult
[1] << 8) | (ExtCsd
->GpSizeMult
[2] << 16));
355 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
357 case EmmcPartitionGP2
:
358 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[3] | (ExtCsd
->GpSizeMult
[4] << 8) | (ExtCsd
->GpSizeMult
[5] << 16));
359 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
361 case EmmcPartitionGP3
:
362 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[6] | (ExtCsd
->GpSizeMult
[7] << 8) | (ExtCsd
->GpSizeMult
[8] << 16));
363 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
365 case EmmcPartitionGP4
:
366 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[9] | (ExtCsd
->GpSizeMult
[10] << 8) | (ExtCsd
->GpSizeMult
[11] << 16));
367 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
371 return EFI_INVALID_PARAMETER
;
375 Partition
->Enable
= TRUE
;
376 Partition
->BlockMedia
.LastBlock
= DivU64x32 (Capacity
, Partition
->BlockMedia
.BlockSize
) - 1;
379 if ((ExtCsd
->EraseGroupDef
& BIT0
) == 0) {
380 if (Csd
->WriteBlLen
< 9) {
381 Partition
->EraseBlock
.EraseLengthGranularity
= 1;
383 Partition
->EraseBlock
.EraseLengthGranularity
= (Csd
->EraseGrpMult
+ 1) * (Csd
->EraseGrpSize
+ 1) * (1 << (Csd
->WriteBlLen
- 9));
386 Partition
->EraseBlock
.EraseLengthGranularity
= 1024 * ExtCsd
->HcEraseGrpSize
;
394 Install BlkIo, BlkIo2 and Ssp protocols for the specified partition in the EMMC device.
396 @param[in] Device The pointer to the EMMC_DEVICE data structure.
397 @param[in] Index The index of the partition.
399 @retval EFI_SUCCESS The protocols are installed successfully.
400 @retval Others Some error occurs when installing the protocols.
404 InstallProtocolOnPartition (
405 IN EMMC_DEVICE
*Device
,
410 EMMC_PARTITION
*Partition
;
411 CONTROLLER_DEVICE_PATH ControlNode
;
412 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
413 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
414 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
415 EFI_HANDLE DeviceHandle
;
420 ParentDevicePath
= Device
->DevicePath
;
422 ControlNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
423 ControlNode
.Header
.SubType
= HW_CONTROLLER_DP
;
424 SetDevicePathNodeLength (&ControlNode
.Header
, sizeof (CONTROLLER_DEVICE_PATH
));
425 ControlNode
.ControllerNumber
= Index
;
427 DevicePath
= AppendDevicePathNode (ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&ControlNode
);
428 if (DevicePath
== NULL
) {
429 Status
= EFI_OUT_OF_RESOURCES
;
434 RemainingDevicePath
= DevicePath
;
435 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
436 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
437 Status
= EFI_ALREADY_STARTED
;
441 Partition
= &Device
->Partition
[Index
];
442 Partition
->DevicePath
= DevicePath
;
443 if (Partition
->Enable
) {
445 // Install BlkIo/BlkIo2/Ssp for the specified partition
447 if (Partition
->PartitionType
!= EmmcPartitionRPMB
) {
448 Status
= gBS
->InstallMultipleProtocolInterfaces (
450 &gEfiDevicePathProtocolGuid
,
451 Partition
->DevicePath
,
452 &gEfiBlockIoProtocolGuid
,
454 &gEfiBlockIo2ProtocolGuid
,
455 &Partition
->BlockIo2
,
456 &gEfiEraseBlockProtocolGuid
,
457 &Partition
->EraseBlock
,
458 &gEfiDiskInfoProtocolGuid
,
459 &Partition
->DiskInfo
,
462 if (EFI_ERROR (Status
)) {
466 if (((Partition
->PartitionType
== EmmcPartitionUserData
) ||
467 (Partition
->PartitionType
== EmmcPartitionBoot1
) ||
468 (Partition
->PartitionType
== EmmcPartitionBoot2
)) &&
469 ((Device
->Csd
.Ccc
& BIT10
) != 0)) {
470 Status
= gBS
->InstallProtocolInterface (
472 &gEfiStorageSecurityCommandProtocolGuid
,
473 EFI_NATIVE_INTERFACE
,
474 &Partition
->StorageSecurity
476 if (EFI_ERROR (Status
)) {
477 gBS
->UninstallMultipleProtocolInterfaces (
479 &gEfiDevicePathProtocolGuid
,
480 Partition
->DevicePath
,
481 &gEfiBlockIoProtocolGuid
,
483 &gEfiBlockIo2ProtocolGuid
,
484 &Partition
->BlockIo2
,
485 &gEfiEraseBlockProtocolGuid
,
486 &Partition
->EraseBlock
,
487 &gEfiDiskInfoProtocolGuid
,
488 &Partition
->DiskInfo
,
496 Device
->Private
->Controller
,
497 &gEfiSdMmcPassThruProtocolGuid
,
498 (VOID
**) &(Device
->Private
->PassThru
),
499 Device
->Private
->DriverBindingHandle
,
501 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
506 Status
= EFI_INVALID_PARAMETER
;
510 if (EFI_ERROR (Status
) && (DevicePath
!= NULL
)) {
511 FreePool (DevicePath
);
518 Scan EMMC Bus to discover the device.
520 @param[in] Private The EMMC driver private data structure.
521 @param[in] Slot The slot number to check device present.
522 @param[in] RemainingDevicePath The pointer to the remaining device path.
524 @retval EFI_SUCCESS Successfully to discover the device and attach
525 SdMmcIoProtocol to it.
526 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
528 @retval EFI_ALREADY_STARTED The device was discovered before.
529 @retval Others Fail to discover the device.
535 IN EMMC_DRIVER_PRIVATE_DATA
*Private
,
537 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
542 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
543 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
544 EFI_DEVICE_PATH_PROTOCOL
*RemainingEmmcDevPath
;
546 EFI_HANDLE DeviceHandle
;
547 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
552 NewDevicePath
= NULL
;
553 RemainingDevicePath
= NULL
;
554 PassThru
= Private
->PassThru
;
555 Device
= &Private
->Device
[Slot
];
558 // Build Device Path to check if the EMMC device present at the slot.
560 Status
= PassThru
->BuildDevicePath (
565 if (EFI_ERROR(Status
)) {
569 if (DevicePath
->SubType
!= MSG_EMMC_DP
) {
570 Status
= EFI_UNSUPPORTED
;
574 NewDevicePath
= AppendDevicePathNode (
575 Private
->ParentDevicePath
,
578 if (NewDevicePath
== NULL
) {
579 Status
= EFI_OUT_OF_RESOURCES
;
584 RemainingEmmcDevPath
= NewDevicePath
;
585 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingEmmcDevPath
, &DeviceHandle
);
587 // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized.
589 if (EFI_ERROR (Status
) || (DeviceHandle
== NULL
) || !IsDevicePathEnd (RemainingEmmcDevPath
)) {
590 Device
->DevicePath
= NewDevicePath
;
592 Device
->Private
= Private
;
594 // Expose user area in the Sd memory card to upper layer.
596 Status
= DiscoverAllPartitions (Device
);
597 if (EFI_ERROR(Status
)) {
598 FreePool (NewDevicePath
);
602 Status
= gBS
->InstallProtocolInterface (
604 &gEfiDevicePathProtocolGuid
,
605 EFI_NATIVE_INTERFACE
,
608 if (EFI_ERROR(Status
)) {
609 FreePool (NewDevicePath
);
613 Device
->ControllerNameTable
= NULL
;
614 GetEmmcModelName (Device
, &Device
->Cid
);
617 gEmmcDxeComponentName
.SupportedLanguages
,
618 &Device
->ControllerNameTable
,
624 gEmmcDxeComponentName2
.SupportedLanguages
,
625 &Device
->ControllerNameTable
,
631 if (RemainingDevicePath
== NULL
) {
633 // Expose all partitions in the Emmc device to upper layer.
635 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
636 InstallProtocolOnPartition (Device
, Index
);
638 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
640 // Enumerate the specified partition
642 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
643 if ((DevicePathType (&Node
->DevPath
) != HARDWARE_DEVICE_PATH
) ||
644 (DevicePathSubType (&Node
->DevPath
) != HW_CONTROLLER_DP
) ||
645 (DevicePathNodeLength (&Node
->DevPath
) != sizeof (CONTROLLER_DEVICE_PATH
))) {
646 Status
= EFI_INVALID_PARAMETER
;
650 Index
= (UINT8
)Node
->Controller
.ControllerNumber
;
651 if (Index
>= EMMC_MAX_PARTITIONS
) {
652 Status
= EFI_INVALID_PARAMETER
;
656 Status
= InstallProtocolOnPartition (Device
, Index
);
660 FreePool (DevicePath
);
666 Tests to see if this driver supports a given controller. If a child device is provided,
667 it further tests to see if this driver supports creating a handle for the specified child device.
669 This function checks to see if the driver specified by This supports the device specified by
670 ControllerHandle. Drivers will typically use the device path attached to
671 ControllerHandle and/or the services from the bus I/O abstraction attached to
672 ControllerHandle to determine if the driver supports ControllerHandle. This function
673 may be called many times during platform initialization. In order to reduce boot times, the tests
674 performed by this function must be very small, and take as little time as possible to execute. This
675 function must not change the state of any hardware devices, and this function must be aware that the
676 device specified by ControllerHandle may already be managed by the same driver or a
677 different driver. This function must match its calls to AllocatePages() with FreePages(),
678 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
679 Since ControllerHandle may have been previously started by the same driver, if a protocol is
680 already in the opened state, then it must not be closed with CloseProtocol(). This is required
681 to guarantee the state of ControllerHandle is not modified by this function.
683 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
684 @param[in] ControllerHandle The handle of the controller to test. This handle
685 must support a protocol interface that supplies
686 an I/O abstraction to the driver.
687 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
688 parameter is ignored by device drivers, and is optional for bus
689 drivers. For bus drivers, if this parameter is not NULL, then
690 the bus driver must determine if the bus controller specified
691 by ControllerHandle and the child controller specified
692 by RemainingDevicePath are both supported by this
695 @retval EFI_SUCCESS The device specified by ControllerHandle and
696 RemainingDevicePath is supported by the driver specified by This.
697 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
698 RemainingDevicePath is already being managed by the driver
700 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
701 RemainingDevicePath is already being managed by a different
702 driver or an application that requires exclusive access.
703 Currently not implemented.
704 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
705 RemainingDevicePath is not supported by the driver specified by This.
709 EmmcDxeDriverBindingSupported (
710 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
711 IN EFI_HANDLE Controller
,
712 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
716 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
717 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
721 // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
723 Status
= gBS
->OpenProtocol (
725 &gEfiSdMmcPassThruProtocolGuid
,
727 This
->DriverBindingHandle
,
729 EFI_OPEN_PROTOCOL_BY_DRIVER
732 if (Status
== EFI_ALREADY_STARTED
) {
736 if (EFI_ERROR (Status
)) {
741 // Test RemainingDevicePath is valid or not.
743 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
744 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
745 if (EFI_ERROR (Status
)) {
747 // Close the I/O Abstraction(s) used to perform the supported test
751 &gEfiSdMmcPassThruProtocolGuid
,
752 This
->DriverBindingHandle
,
760 // Close the I/O Abstraction(s) used to perform the supported test
764 &gEfiSdMmcPassThruProtocolGuid
,
765 This
->DriverBindingHandle
,
770 // Open the EFI Device Path protocol needed to perform the supported test
772 Status
= gBS
->OpenProtocol (
774 &gEfiDevicePathProtocolGuid
,
775 (VOID
**) &ParentDevicePath
,
776 This
->DriverBindingHandle
,
778 EFI_OPEN_PROTOCOL_GET_PROTOCOL
784 Starts a device controller or a bus controller.
786 The Start() function is designed to be invoked from the EFI boot service ConnectController().
787 As a result, much of the error checking on the parameters to Start() has been moved into this
788 common boot service. It is legal to call Start() from other locations,
789 but the following calling restrictions must be followed or the system behavior will not be deterministic.
790 1. ControllerHandle must be a valid EFI_HANDLE.
791 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
792 EFI_DEVICE_PATH_PROTOCOL.
793 3. Prior to calling Start(), the Supported() function for the driver specified by This must
794 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
796 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
797 @param[in] ControllerHandle The handle of the controller to start. This handle
798 must support a protocol interface that supplies
799 an I/O abstraction to the driver.
800 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
801 parameter is ignored by device drivers, and is optional for bus
802 drivers. For a bus driver, if this parameter is NULL, then handles
803 for all the children of Controller are created by this driver.
804 If this parameter is not NULL and the first Device Path Node is
805 not the End of Device Path Node, then only the handle for the
806 child device specified by the first Device Path Node of
807 RemainingDevicePath is created by this driver.
808 If the first Device Path Node of RemainingDevicePath is
809 the End of Device Path Node, no child handle is created by this
812 @retval EFI_SUCCESS The device was started.
813 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
814 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
815 @retval Others The driver failded to start the device.
820 EmmcDxeDriverBindingStart (
821 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
822 IN EFI_HANDLE Controller
,
823 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
827 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
828 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
829 EMMC_DRIVER_PRIVATE_DATA
*Private
;
834 Status
= gBS
->OpenProtocol (
836 &gEfiSdMmcPassThruProtocolGuid
,
838 This
->DriverBindingHandle
,
840 EFI_OPEN_PROTOCOL_BY_DRIVER
842 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
847 // Check EFI_ALREADY_STARTED to reuse the original EMMC_DRIVER_PRIVATE_DATA.
849 if (Status
!= EFI_ALREADY_STARTED
) {
850 Private
= AllocateZeroPool (sizeof (EMMC_DRIVER_PRIVATE_DATA
));
851 if (Private
== NULL
) {
852 Status
= EFI_OUT_OF_RESOURCES
;
856 Status
= gBS
->OpenProtocol (
858 &gEfiDevicePathProtocolGuid
,
859 (VOID
**) &ParentDevicePath
,
860 This
->DriverBindingHandle
,
862 EFI_OPEN_PROTOCOL_GET_PROTOCOL
864 ASSERT_EFI_ERROR (Status
);
865 Private
->PassThru
= PassThru
;
866 Private
->Controller
= Controller
;
867 Private
->ParentDevicePath
= ParentDevicePath
;
868 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
870 Status
= gBS
->InstallProtocolInterface (
873 EFI_NATIVE_INTERFACE
,
876 if (EFI_ERROR (Status
)) {
880 Status
= gBS
->OpenProtocol (
884 This
->DriverBindingHandle
,
886 EFI_OPEN_PROTOCOL_GET_PROTOCOL
888 if (EFI_ERROR (Status
)) {
893 if (RemainingDevicePath
== NULL
) {
896 Status
= PassThru
->GetNextSlot (PassThru
, &Slot
);
897 if (EFI_ERROR (Status
)) {
899 // Cannot find more legal slots.
901 Status
= EFI_SUCCESS
;
905 Status
= DiscoverEmmcDevice (Private
, Slot
, NULL
);
906 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
910 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
911 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
912 if (!EFI_ERROR (Status
)) {
913 Status
= DiscoverEmmcDevice (Private
, Slot
, NextDevicePathNode (RemainingDevicePath
));
918 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
921 &gEfiSdMmcPassThruProtocolGuid
,
922 This
->DriverBindingHandle
,
926 if (Private
!= NULL
) {
927 gBS
->UninstallMultipleProtocolInterfaces (
940 Stops a device controller or a bus controller.
942 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
943 As a result, much of the error checking on the parameters to Stop() has been moved
944 into this common boot service. It is legal to call Stop() from other locations,
945 but the following calling restrictions must be followed or the system behavior will not be deterministic.
946 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
947 same driver's Start() function.
948 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
949 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
950 Start() function, and the Start() function must have called OpenProtocol() on
951 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
953 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
954 @param[in] ControllerHandle A handle to the device being stopped. The handle must
955 support a bus specific I/O protocol for the driver
956 to use to stop the device.
957 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
958 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
959 if NumberOfChildren is 0.
961 @retval EFI_SUCCESS The device was stopped.
962 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
967 EmmcDxeDriverBindingStop (
968 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
969 IN EFI_HANDLE Controller
,
970 IN UINTN NumberOfChildren
,
971 IN EFI_HANDLE
*ChildHandleBuffer
975 BOOLEAN AllChildrenStopped
;
977 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
978 EMMC_DRIVER_PRIVATE_DATA
*Private
;
980 EMMC_PARTITION
*Partition
;
981 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
982 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
983 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
985 LIST_ENTRY
*NextLink
;
986 EMMC_REQUEST
*Request
;
990 if (NumberOfChildren
== 0) {
991 Status
= gBS
->OpenProtocol (
995 This
->DriverBindingHandle
,
997 EFI_OPEN_PROTOCOL_GET_PROTOCOL
999 if (EFI_ERROR (Status
)) {
1000 return EFI_DEVICE_ERROR
;
1003 for (Index
= 0; Index
< EMMC_MAX_DEVICES
; Index
++) {
1004 Device
= &Private
->Device
[Index
];
1005 Status
= gBS
->OpenProtocol (
1007 &gEfiDevicePathProtocolGuid
,
1008 (VOID
**) &DevicePath
,
1009 This
->DriverBindingHandle
,
1011 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1013 if (EFI_ERROR (Status
)) {
1016 ASSERT (DevicePath
== Device
->DevicePath
);
1017 gBS
->UninstallProtocolInterface (
1019 &gEfiDevicePathProtocolGuid
,
1022 FreePool (Device
->DevicePath
);
1025 gBS
->UninstallProtocolInterface (
1030 gBS
->CloseProtocol (
1032 &gEfiSdMmcPassThruProtocolGuid
,
1033 This
->DriverBindingHandle
,
1041 AllChildrenStopped
= TRUE
;
1043 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1044 Status
= gBS
->OpenProtocol (
1045 ChildHandleBuffer
[Index
],
1046 &gEfiBlockIoProtocolGuid
,
1048 This
->DriverBindingHandle
,
1050 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1052 if (EFI_ERROR (Status
)) {
1053 Status
= gBS
->OpenProtocol (
1054 ChildHandleBuffer
[Index
],
1055 &gEfiBlockIo2ProtocolGuid
,
1056 (VOID
**) &BlockIo2
,
1057 This
->DriverBindingHandle
,
1059 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1061 if (EFI_ERROR (Status
)) {
1062 AllChildrenStopped
= FALSE
;
1067 if (BlockIo
!= NULL
) {
1068 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO (BlockIo
);
1070 ASSERT (BlockIo2
!= NULL
);
1071 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO2 (BlockIo2
);
1074 for (Link
= GetFirstNode (&Partition
->Queue
);
1075 !IsNull (&Partition
->Queue
, Link
);
1077 NextLink
= GetNextNode (&Partition
->Queue
, Link
);
1079 RemoveEntryList (Link
);
1080 Request
= EMMC_REQUEST_FROM_LINK (Link
);
1082 gBS
->CloseEvent (Request
->Event
);
1083 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
1085 if (Request
->IsEnd
) {
1086 gBS
->SignalEvent (Request
->Token
->Event
);
1093 // Close the child handle
1095 Status
= gBS
->CloseProtocol (
1097 &gEfiSdMmcPassThruProtocolGuid
,
1098 This
->DriverBindingHandle
,
1099 ChildHandleBuffer
[Index
]
1102 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1103 ChildHandleBuffer
[Index
],
1104 &gEfiDevicePathProtocolGuid
,
1105 Partition
->DevicePath
,
1106 &gEfiBlockIoProtocolGuid
,
1107 &Partition
->BlockIo
,
1108 &gEfiBlockIo2ProtocolGuid
,
1109 &Partition
->BlockIo2
,
1110 &gEfiEraseBlockProtocolGuid
,
1111 &Partition
->EraseBlock
,
1112 &gEfiDiskInfoProtocolGuid
,
1113 &Partition
->DiskInfo
,
1116 if (EFI_ERROR (Status
)) {
1117 AllChildrenStopped
= FALSE
;
1120 &gEfiSdMmcPassThruProtocolGuid
,
1121 (VOID
**)&Partition
->Device
->Private
->PassThru
,
1122 This
->DriverBindingHandle
,
1123 ChildHandleBuffer
[Index
],
1124 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1130 // If Storage Security Command Protocol is installed, then uninstall this protocol.
1132 Status
= gBS
->OpenProtocol (
1133 ChildHandleBuffer
[Index
],
1134 &gEfiStorageSecurityCommandProtocolGuid
,
1135 (VOID
**) &StorageSecurity
,
1136 This
->DriverBindingHandle
,
1138 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1141 if (!EFI_ERROR (Status
)) {
1142 Status
= gBS
->UninstallProtocolInterface (
1143 ChildHandleBuffer
[Index
],
1144 &gEfiStorageSecurityCommandProtocolGuid
,
1145 &Partition
->StorageSecurity
1147 if (EFI_ERROR (Status
)) {
1150 &gEfiSdMmcPassThruProtocolGuid
,
1151 (VOID
**) &Partition
->Device
->Private
->PassThru
,
1152 This
->DriverBindingHandle
,
1153 ChildHandleBuffer
[Index
],
1154 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1156 AllChildrenStopped
= FALSE
;
1161 FreePool (Partition
->DevicePath
);
1164 if (!AllChildrenStopped
) {
1165 return EFI_DEVICE_ERROR
;
1172 The user Entry Point for module EmmcDxe. The user code starts with this function.
1174 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1175 @param[in] SystemTable A pointer to the EFI System Table.
1177 @retval EFI_SUCCESS The entry point is executed successfully.
1178 @retval other Some errors occur when executing this entry point.
1184 IN EFI_HANDLE ImageHandle
,
1185 IN EFI_SYSTEM_TABLE
*SystemTable
1191 // Install driver model protocol(s).
1193 Status
= EfiLibInstallDriverBindingComponentName2 (
1196 &gEmmcDxeDriverBinding
,
1198 &gEmmcDxeComponentName
,
1199 &gEmmcDxeComponentName2
1201 ASSERT_EFI_ERROR (Status
);