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 - 2017, Intel Corporation. All rights reserved.<BR>
8 This program and the accompanying materials
9 are licensed and made available under the terms and conditions of the BSD License
10 which accompanies this distribution. The full text of the license may be found at
11 http://opensource.org/licenses/bsd-license.php
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 // EmmcDxe Driver Binding Protocol Instance
23 EFI_DRIVER_BINDING_PROTOCOL gEmmcDxeDriverBinding
= {
24 EmmcDxeDriverBindingSupported
,
25 EmmcDxeDriverBindingStart
,
26 EmmcDxeDriverBindingStop
,
33 // Template for Emmc Partitions.
35 EMMC_PARTITION mEmmcPartitionTemplate
= {
36 EMMC_PARTITION_SIGNATURE
, // Signature
38 EmmcPartitionUnknown
, // PartitionType
42 EFI_BLOCK_IO_PROTOCOL_REVISION
,
58 FALSE
, // RemovableMedia
60 FALSE
, // LogicPartition
62 FALSE
, // WritingCache
68 EmmcSecurityProtocolIn
,
69 EmmcSecurityProtocolOut
72 EFI_ERASE_BLOCK_PROTOCOL_REVISION
,
77 EFI_DISK_INFO_SD_MMC_INTERFACE_GUID
,
80 EmmcDiskInfoSenseData
,
91 Decode and print EMMC CSD Register content.
93 @param[in] Csd Pointer to EMMC_CSD data structure.
95 @retval EFI_SUCCESS The function completed successfully
102 DEBUG((DEBUG_INFO
, "== Dump Emmc Csd Register==\n"));
103 DEBUG((DEBUG_INFO
, " CSD structure 0x%x\n", Csd
->CsdStructure
));
104 DEBUG((DEBUG_INFO
, " System specification version 0x%x\n", Csd
->SpecVers
));
105 DEBUG((DEBUG_INFO
, " Data read access-time 1 0x%x\n", Csd
->Taac
));
106 DEBUG((DEBUG_INFO
, " Data read access-time 2 0x%x\n", Csd
->Nsac
));
107 DEBUG((DEBUG_INFO
, " Max. bus clock frequency 0x%x\n", Csd
->TranSpeed
));
108 DEBUG((DEBUG_INFO
, " Device command classes 0x%x\n", Csd
->Ccc
));
109 DEBUG((DEBUG_INFO
, " Max. read data block length 0x%x\n", Csd
->ReadBlLen
));
110 DEBUG((DEBUG_INFO
, " Partial blocks for read allowed 0x%x\n", Csd
->ReadBlPartial
));
111 DEBUG((DEBUG_INFO
, " Write block misalignment 0x%x\n", Csd
->WriteBlkMisalign
));
112 DEBUG((DEBUG_INFO
, " Read block misalignment 0x%x\n", Csd
->ReadBlkMisalign
));
113 DEBUG((DEBUG_INFO
, " DSR implemented 0x%x\n", Csd
->DsrImp
));
114 DEBUG((DEBUG_INFO
, " Device size 0x%x\n", Csd
->CSizeLow
| (Csd
->CSizeHigh
<< 2)));
115 DEBUG((DEBUG_INFO
, " Max. read current @ VDD min 0x%x\n", Csd
->VddRCurrMin
));
116 DEBUG((DEBUG_INFO
, " Max. read current @ VDD max 0x%x\n", Csd
->VddRCurrMax
));
117 DEBUG((DEBUG_INFO
, " Max. write current @ VDD min 0x%x\n", Csd
->VddWCurrMin
));
118 DEBUG((DEBUG_INFO
, " Max. write current @ VDD max 0x%x\n", Csd
->VddWCurrMax
));
119 DEBUG((DEBUG_INFO
, " Device size multiplier 0x%x\n", Csd
->CSizeMult
));
120 DEBUG((DEBUG_INFO
, " Erase group size 0x%x\n", Csd
->EraseGrpSize
));
121 DEBUG((DEBUG_INFO
, " Erase group size multiplier 0x%x\n", Csd
->EraseGrpMult
));
122 DEBUG((DEBUG_INFO
, " Write protect group size 0x%x\n", Csd
->WpGrpSize
));
123 DEBUG((DEBUG_INFO
, " Write protect group enable 0x%x\n", Csd
->WpGrpEnable
));
124 DEBUG((DEBUG_INFO
, " Manufacturer default ECC 0x%x\n", Csd
->DefaultEcc
));
125 DEBUG((DEBUG_INFO
, " Write speed factor 0x%x\n", Csd
->R2WFactor
));
126 DEBUG((DEBUG_INFO
, " Max. write data block length 0x%x\n", Csd
->WriteBlLen
));
127 DEBUG((DEBUG_INFO
, " Partial blocks for write allowed 0x%x\n", Csd
->WriteBlPartial
));
128 DEBUG((DEBUG_INFO
, " Content protection application 0x%x\n", Csd
->ContentProtApp
));
129 DEBUG((DEBUG_INFO
, " File format group 0x%x\n", Csd
->FileFormatGrp
));
130 DEBUG((DEBUG_INFO
, " Copy flag (OTP) 0x%x\n", Csd
->Copy
));
131 DEBUG((DEBUG_INFO
, " Permanent write protection 0x%x\n", Csd
->PermWriteProtect
));
132 DEBUG((DEBUG_INFO
, " Temporary write protection 0x%x\n", Csd
->TmpWriteProtect
));
133 DEBUG((DEBUG_INFO
, " File format 0x%x\n", Csd
->FileFormat
));
134 DEBUG((DEBUG_INFO
, " ECC code 0x%x\n", Csd
->Ecc
));
140 Decode and print EMMC EXT_CSD Register content.
142 @param[in] ExtCsd Pointer to the EMMC_EXT_CSD data structure.
144 @retval EFI_SUCCESS The function completed successfully
148 IN EMMC_EXT_CSD
*ExtCsd
151 DEBUG((DEBUG_INFO
, "==Dump Emmc ExtCsd Register==\n"));
152 DEBUG((DEBUG_INFO
, " Supported Command Sets 0x%x\n", ExtCsd
->CmdSet
));
153 DEBUG((DEBUG_INFO
, " HPI features 0x%x\n", ExtCsd
->HpiFeatures
));
154 DEBUG((DEBUG_INFO
, " Background operations support 0x%x\n", ExtCsd
->BkOpsSupport
));
155 DEBUG((DEBUG_INFO
, " Background operations status 0x%x\n", ExtCsd
->BkopsStatus
));
156 DEBUG((DEBUG_INFO
, " Number of correctly programmed sectors 0x%x\n", *((UINT32
*)&ExtCsd
->CorrectlyPrgSectorsNum
[0])));
157 DEBUG((DEBUG_INFO
, " Initialization time after partitioning 0x%x\n", ExtCsd
->IniTimeoutAp
));
158 DEBUG((DEBUG_INFO
, " TRIM Multiplier 0x%x\n", ExtCsd
->TrimMult
));
159 DEBUG((DEBUG_INFO
, " Secure Feature support 0x%x\n", ExtCsd
->SecFeatureSupport
));
160 DEBUG((DEBUG_INFO
, " Secure Erase Multiplier 0x%x\n", ExtCsd
->SecEraseMult
));
161 DEBUG((DEBUG_INFO
, " Secure TRIM Multiplier 0x%x\n", ExtCsd
->SecTrimMult
));
162 DEBUG((DEBUG_INFO
, " Boot information 0x%x\n", ExtCsd
->BootInfo
));
163 DEBUG((DEBUG_INFO
, " Boot partition size 0x%x\n", ExtCsd
->BootSizeMult
));
164 DEBUG((DEBUG_INFO
, " Access size 0x%x\n", ExtCsd
->AccSize
));
165 DEBUG((DEBUG_INFO
, " High-capacity erase unit size 0x%x\n", ExtCsd
->HcEraseGrpSize
));
166 DEBUG((DEBUG_INFO
, " High-capacity erase timeout 0x%x\n", ExtCsd
->EraseTimeoutMult
));
167 DEBUG((DEBUG_INFO
, " Reliable write sector count 0x%x\n", ExtCsd
->RelWrSecC
));
168 DEBUG((DEBUG_INFO
, " High-capacity write protect group size 0x%x\n", ExtCsd
->HcWpGrpSize
));
169 DEBUG((DEBUG_INFO
, " Sleep/awake timeout 0x%x\n", ExtCsd
->SATimeout
));
170 DEBUG((DEBUG_INFO
, " Sector Count 0x%x\n", *((UINT32
*)&ExtCsd
->SecCount
[0])));
171 DEBUG((DEBUG_INFO
, " Partition switching timing 0x%x\n", ExtCsd
->PartitionSwitchTime
));
172 DEBUG((DEBUG_INFO
, " Out-of-interrupt busy timing 0x%x\n", ExtCsd
->OutOfInterruptTime
));
173 DEBUG((DEBUG_INFO
, " I/O Driver Strength 0x%x\n", ExtCsd
->DriverStrength
));
174 DEBUG((DEBUG_INFO
, " Device type 0x%x\n", ExtCsd
->DeviceType
));
175 DEBUG((DEBUG_INFO
, " CSD STRUCTURE 0x%x\n", ExtCsd
->CsdStructure
));
176 DEBUG((DEBUG_INFO
, " Extended CSD revision 0x%x\n", ExtCsd
->ExtCsdRev
));
177 DEBUG((DEBUG_INFO
, " Command set 0x%x\n", ExtCsd
->CmdSet
));
178 DEBUG((DEBUG_INFO
, " Command set revision 0x%x\n", ExtCsd
->CmdSetRev
));
179 DEBUG((DEBUG_INFO
, " Power class 0x%x\n", ExtCsd
->PowerClass
));
180 DEBUG((DEBUG_INFO
, " High-speed interface timing 0x%x\n", ExtCsd
->HsTiming
));
181 DEBUG((DEBUG_INFO
, " Bus width mode 0x%x\n", ExtCsd
->BusWidth
));
182 DEBUG((DEBUG_INFO
, " Erased memory content 0x%x\n", ExtCsd
->ErasedMemCont
));
183 DEBUG((DEBUG_INFO
, " Partition configuration 0x%x\n", ExtCsd
->PartitionConfig
));
184 DEBUG((DEBUG_INFO
, " Boot config protection 0x%x\n", ExtCsd
->BootConfigProt
));
185 DEBUG((DEBUG_INFO
, " Boot bus Conditions 0x%x\n", ExtCsd
->BootBusConditions
));
186 DEBUG((DEBUG_INFO
, " High-density erase group definition 0x%x\n", ExtCsd
->EraseGroupDef
));
187 DEBUG((DEBUG_INFO
, " Boot write protection status register 0x%x\n", ExtCsd
->BootWpStatus
));
188 DEBUG((DEBUG_INFO
, " Boot area write protection register 0x%x\n", ExtCsd
->BootWp
));
189 DEBUG((DEBUG_INFO
, " User area write protection register 0x%x\n", ExtCsd
->UserWp
));
190 DEBUG((DEBUG_INFO
, " FW configuration 0x%x\n", ExtCsd
->FwConfig
));
191 DEBUG((DEBUG_INFO
, " RPMB Size 0x%x\n", ExtCsd
->RpmbSizeMult
));
192 DEBUG((DEBUG_INFO
, " H/W reset function 0x%x\n", ExtCsd
->RstFunction
));
193 DEBUG((DEBUG_INFO
, " Partitioning Support 0x%x\n", ExtCsd
->PartitioningSupport
));
194 DEBUG((DEBUG_INFO
, " Max Enhanced Area Size 0x%02x%02x%02x\n", \
195 ExtCsd
->MaxEnhSizeMult
[2], ExtCsd
->MaxEnhSizeMult
[1], ExtCsd
->MaxEnhSizeMult
[0]));
196 DEBUG((DEBUG_INFO
, " Partitions attribute 0x%x\n", ExtCsd
->PartitionsAttribute
));
197 DEBUG((DEBUG_INFO
, " Partitioning Setting 0x%x\n", ExtCsd
->PartitionSettingCompleted
));
198 DEBUG((DEBUG_INFO
, " General Purpose Partition 1 Size 0x%02x%02x%02x\n", \
199 ExtCsd
->GpSizeMult
[2], ExtCsd
->GpSizeMult
[1], ExtCsd
->GpSizeMult
[0]));
200 DEBUG((DEBUG_INFO
, " General Purpose Partition 2 Size 0x%02x%02x%02x\n", \
201 ExtCsd
->GpSizeMult
[5], ExtCsd
->GpSizeMult
[4], ExtCsd
->GpSizeMult
[3]));
202 DEBUG((DEBUG_INFO
, " General Purpose Partition 3 Size 0x%02x%02x%02x\n", \
203 ExtCsd
->GpSizeMult
[8], ExtCsd
->GpSizeMult
[7], ExtCsd
->GpSizeMult
[6]));
204 DEBUG((DEBUG_INFO
, " General Purpose Partition 4 Size 0x%02x%02x%02x\n", \
205 ExtCsd
->GpSizeMult
[11], ExtCsd
->GpSizeMult
[10], ExtCsd
->GpSizeMult
[9]));
206 DEBUG((DEBUG_INFO
, " Enhanced User Data Area Size 0x%02x%02x%02x\n", \
207 ExtCsd
->EnhSizeMult
[2], ExtCsd
->EnhSizeMult
[1], ExtCsd
->EnhSizeMult
[0]));
208 DEBUG((DEBUG_INFO
, " Enhanced User Data Start Address 0x%x\n", *((UINT32
*)&ExtCsd
->EnhStartAddr
[0])));
209 DEBUG((DEBUG_INFO
, " Bad Block Management mode 0x%x\n", ExtCsd
->SecBadBlkMgmnt
));
210 DEBUG((DEBUG_INFO
, " Native sector size 0x%x\n", ExtCsd
->NativeSectorSize
));
211 DEBUG((DEBUG_INFO
, " Sector size emulation 0x%x\n", ExtCsd
->UseNativeSector
));
212 DEBUG((DEBUG_INFO
, " Sector size 0x%x\n", ExtCsd
->DataSectorSize
));
218 Get EMMC device model name.
220 @param[in, out] Device The pointer to the EMMC_DEVICE data structure.
221 @param[in] Cid Pointer to EMMC_CID data structure.
223 @retval EFI_SUCCESS The function completed successfully
228 IN OUT EMMC_DEVICE
*Device
,
232 CHAR8 String
[EMMC_MODEL_NAME_MAX_LEN
];
234 ZeroMem (String
, sizeof (String
));
235 CopyMem (String
, &Cid
->OemId
, sizeof (Cid
->OemId
));
236 String
[sizeof (Cid
->OemId
)] = ' ';
237 CopyMem (String
+ sizeof (Cid
->OemId
) + 1, Cid
->ProductName
, sizeof (Cid
->ProductName
));
238 String
[sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
)] = ' ';
239 CopyMem (String
+ sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
) + 1, Cid
->ProductSerialNumber
, sizeof (Cid
->ProductSerialNumber
));
241 AsciiStrToUnicodeStrS (String
, Device
->ModelName
, sizeof (Device
->ModelName
) / sizeof (Device
->ModelName
[0]));
247 Discover all partitions in the EMMC device.
249 @param[in] Device The pointer to the EMMC_DEVICE data structure.
251 @retval EFI_SUCCESS All the partitions in the device are successfully enumerated.
252 @return Others Some error occurs when enumerating the partitions.
256 DiscoverAllPartitions (
257 IN EMMC_DEVICE
*Device
261 EMMC_PARTITION
*Partition
;
264 EMMC_EXT_CSD
*ExtCsd
;
274 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
275 if (EFI_ERROR (Status
)) {
279 // Deselect the device to force it enter stby mode before getting CSD
281 // Note here we don't judge return status as some EMMC devices return
282 // error but the state has been stby.
284 EmmcSelect (Device
, 0);
286 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
287 if (EFI_ERROR (Status
)) {
292 Status
= EmmcGetCsd (Device
, Slot
+ 1, Csd
);
293 if (EFI_ERROR (Status
)) {
298 if ((Csd
->CSizeLow
| Csd
->CSizeHigh
<< 2) == 0xFFF) {
299 Device
->SectorAddressing
= TRUE
;
301 Device
->SectorAddressing
= FALSE
;
305 Status
= EmmcGetCid (Device
, Slot
+ 1, Cid
);
306 if (EFI_ERROR (Status
)) {
310 Status
= EmmcSelect (Device
, Slot
+ 1);
311 if (EFI_ERROR (Status
)) {
315 ExtCsd
= &Device
->ExtCsd
;
316 Status
= EmmcGetExtCsd (Device
, ExtCsd
);
317 if (EFI_ERROR (Status
)) {
322 if (ExtCsd
->ExtCsdRev
< 5) {
323 DEBUG ((EFI_D_ERROR
, "The EMMC device version is too low, we don't support!!!\n"));
324 return EFI_UNSUPPORTED
;
327 if ((ExtCsd
->PartitioningSupport
& BIT0
) != BIT0
) {
328 DEBUG ((EFI_D_ERROR
, "The EMMC device doesn't support Partition Feature!!!\n"));
329 return EFI_UNSUPPORTED
;
332 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
333 Partition
= &Device
->Partition
[Index
];
334 CopyMem (Partition
, &mEmmcPartitionTemplate
, sizeof (EMMC_PARTITION
));
335 Partition
->Device
= Device
;
336 InitializeListHead (&Partition
->Queue
);
337 Partition
->BlockIo
.Media
= &Partition
->BlockMedia
;
338 Partition
->BlockIo2
.Media
= &Partition
->BlockMedia
;
339 Partition
->PartitionType
= Index
;
340 Partition
->BlockMedia
.IoAlign
= Device
->Private
->PassThru
->IoAlign
;
341 Partition
->BlockMedia
.BlockSize
= 0x200;
342 Partition
->BlockMedia
.LastBlock
= 0x00;
343 Partition
->BlockMedia
.RemovableMedia
= FALSE
;
344 Partition
->BlockMedia
.MediaPresent
= TRUE
;
345 Partition
->BlockMedia
.LogicalPartition
= FALSE
;
348 case EmmcPartitionUserData
:
349 SecCount
= *(UINT32
*)&ExtCsd
->SecCount
;
350 Capacity
= MultU64x32 ((UINT64
) SecCount
, 0x200);
352 case EmmcPartitionBoot1
:
353 case EmmcPartitionBoot2
:
354 Capacity
= ExtCsd
->BootSizeMult
* SIZE_128KB
;
356 case EmmcPartitionRPMB
:
357 Capacity
= ExtCsd
->RpmbSizeMult
* SIZE_128KB
;
359 case EmmcPartitionGP1
:
360 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[0] | (ExtCsd
->GpSizeMult
[1] << 8) | (ExtCsd
->GpSizeMult
[2] << 16));
361 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
363 case EmmcPartitionGP2
:
364 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[3] | (ExtCsd
->GpSizeMult
[4] << 8) | (ExtCsd
->GpSizeMult
[5] << 16));
365 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
367 case EmmcPartitionGP3
:
368 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[6] | (ExtCsd
->GpSizeMult
[7] << 8) | (ExtCsd
->GpSizeMult
[8] << 16));
369 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
371 case EmmcPartitionGP4
:
372 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[9] | (ExtCsd
->GpSizeMult
[10] << 8) | (ExtCsd
->GpSizeMult
[11] << 16));
373 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
377 return EFI_INVALID_PARAMETER
;
381 Partition
->Enable
= TRUE
;
382 Partition
->BlockMedia
.LastBlock
= DivU64x32 (Capacity
, Partition
->BlockMedia
.BlockSize
) - 1;
385 if ((ExtCsd
->EraseGroupDef
& BIT0
) == 0) {
386 if (Csd
->WriteBlLen
< 9) {
387 Partition
->EraseBlock
.EraseLengthGranularity
= 1;
389 Partition
->EraseBlock
.EraseLengthGranularity
= (Csd
->EraseGrpMult
+ 1) * (Csd
->EraseGrpSize
+ 1) * (1 << (Csd
->WriteBlLen
- 9));
392 Partition
->EraseBlock
.EraseLengthGranularity
= 1024 * ExtCsd
->HcEraseGrpSize
;
400 Install BlkIo, BlkIo2 and Ssp protocols for the specified partition in the EMMC device.
402 @param[in] Device The pointer to the EMMC_DEVICE data structure.
403 @param[in] Index The index of the partition.
405 @retval EFI_SUCCESS The protocols are installed successfully.
406 @retval Others Some error occurs when installing the protocols.
410 InstallProtocolOnPartition (
411 IN EMMC_DEVICE
*Device
,
416 EMMC_PARTITION
*Partition
;
417 CONTROLLER_DEVICE_PATH ControlNode
;
418 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
419 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
420 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
421 EFI_HANDLE DeviceHandle
;
426 ParentDevicePath
= Device
->DevicePath
;
428 ControlNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
429 ControlNode
.Header
.SubType
= HW_CONTROLLER_DP
;
430 SetDevicePathNodeLength (&ControlNode
.Header
, sizeof (CONTROLLER_DEVICE_PATH
));
431 ControlNode
.ControllerNumber
= Index
;
433 DevicePath
= AppendDevicePathNode (ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&ControlNode
);
434 if (DevicePath
== NULL
) {
435 Status
= EFI_OUT_OF_RESOURCES
;
440 RemainingDevicePath
= DevicePath
;
441 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
442 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
443 Status
= EFI_ALREADY_STARTED
;
447 Partition
= &Device
->Partition
[Index
];
448 Partition
->DevicePath
= DevicePath
;
449 if (Partition
->Enable
) {
451 // Install BlkIo/BlkIo2/Ssp for the specified partition
453 if (Partition
->PartitionType
!= EmmcPartitionRPMB
) {
454 Status
= gBS
->InstallMultipleProtocolInterfaces (
456 &gEfiDevicePathProtocolGuid
,
457 Partition
->DevicePath
,
458 &gEfiBlockIoProtocolGuid
,
460 &gEfiBlockIo2ProtocolGuid
,
461 &Partition
->BlockIo2
,
462 &gEfiEraseBlockProtocolGuid
,
463 &Partition
->EraseBlock
,
464 &gEfiDiskInfoProtocolGuid
,
465 &Partition
->DiskInfo
,
468 if (EFI_ERROR (Status
)) {
472 if (((Partition
->PartitionType
== EmmcPartitionUserData
) ||
473 (Partition
->PartitionType
== EmmcPartitionBoot1
) ||
474 (Partition
->PartitionType
== EmmcPartitionBoot2
)) &&
475 ((Device
->Csd
.Ccc
& BIT10
) != 0)) {
476 Status
= gBS
->InstallProtocolInterface (
478 &gEfiStorageSecurityCommandProtocolGuid
,
479 EFI_NATIVE_INTERFACE
,
480 &Partition
->StorageSecurity
482 if (EFI_ERROR (Status
)) {
483 gBS
->UninstallMultipleProtocolInterfaces (
485 &gEfiDevicePathProtocolGuid
,
486 Partition
->DevicePath
,
487 &gEfiBlockIoProtocolGuid
,
489 &gEfiBlockIo2ProtocolGuid
,
490 &Partition
->BlockIo2
,
491 &gEfiEraseBlockProtocolGuid
,
492 &Partition
->EraseBlock
,
493 &gEfiDiskInfoProtocolGuid
,
494 &Partition
->DiskInfo
,
502 Device
->Private
->Controller
,
503 &gEfiSdMmcPassThruProtocolGuid
,
504 (VOID
**) &(Device
->Private
->PassThru
),
505 Device
->Private
->DriverBindingHandle
,
507 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
512 Status
= EFI_INVALID_PARAMETER
;
516 if (EFI_ERROR (Status
) && (DevicePath
!= NULL
)) {
517 FreePool (DevicePath
);
524 Scan EMMC Bus to discover the device.
526 @param[in] Private The EMMC driver private data structure.
527 @param[in] Slot The slot number to check device present.
528 @param[in] RemainingDevicePath The pointer to the remaining device path.
530 @retval EFI_SUCCESS Successfully to discover the device and attach
531 SdMmcIoProtocol to it.
532 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
534 @retval EFI_ALREADY_STARTED The device was discovered before.
535 @retval Others Fail to discover the device.
541 IN EMMC_DRIVER_PRIVATE_DATA
*Private
,
543 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
548 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
549 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
550 EFI_DEVICE_PATH_PROTOCOL
*RemainingEmmcDevPath
;
552 EFI_HANDLE DeviceHandle
;
553 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
558 NewDevicePath
= NULL
;
559 RemainingDevicePath
= NULL
;
560 PassThru
= Private
->PassThru
;
561 Device
= &Private
->Device
[Slot
];
564 // Build Device Path to check if the EMMC device present at the slot.
566 Status
= PassThru
->BuildDevicePath (
571 if (EFI_ERROR(Status
)) {
575 if (DevicePath
->SubType
!= MSG_EMMC_DP
) {
576 Status
= EFI_UNSUPPORTED
;
580 NewDevicePath
= AppendDevicePathNode (
581 Private
->ParentDevicePath
,
584 if (NewDevicePath
== NULL
) {
585 Status
= EFI_OUT_OF_RESOURCES
;
590 RemainingEmmcDevPath
= NewDevicePath
;
591 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingEmmcDevPath
, &DeviceHandle
);
593 // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized.
595 if (EFI_ERROR (Status
) || (DeviceHandle
== NULL
) || !IsDevicePathEnd (RemainingEmmcDevPath
)) {
596 Device
->DevicePath
= NewDevicePath
;
598 Device
->Private
= Private
;
600 // Expose user area in the Sd memory card to upper layer.
602 Status
= DiscoverAllPartitions (Device
);
603 if (EFI_ERROR(Status
)) {
604 FreePool (NewDevicePath
);
608 Status
= gBS
->InstallProtocolInterface (
610 &gEfiDevicePathProtocolGuid
,
611 EFI_NATIVE_INTERFACE
,
614 if (EFI_ERROR(Status
)) {
615 FreePool (NewDevicePath
);
619 Device
->ControllerNameTable
= NULL
;
620 GetEmmcModelName (Device
, &Device
->Cid
);
623 gEmmcDxeComponentName
.SupportedLanguages
,
624 &Device
->ControllerNameTable
,
630 gEmmcDxeComponentName
.SupportedLanguages
,
631 &Device
->ControllerNameTable
,
637 if (RemainingDevicePath
== NULL
) {
639 // Expose all partitions in the Emmc device to upper layer.
641 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
642 InstallProtocolOnPartition (Device
, Index
);
644 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
646 // Enumerate the specified partition
648 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
649 if ((DevicePathType (&Node
->DevPath
) != HARDWARE_DEVICE_PATH
) ||
650 (DevicePathSubType (&Node
->DevPath
) != HW_CONTROLLER_DP
) ||
651 (DevicePathNodeLength (&Node
->DevPath
) != sizeof (CONTROLLER_DEVICE_PATH
))) {
652 Status
= EFI_INVALID_PARAMETER
;
656 Index
= (UINT8
)Node
->Controller
.ControllerNumber
;
657 if (Index
>= EMMC_MAX_PARTITIONS
) {
658 Status
= EFI_INVALID_PARAMETER
;
662 Status
= InstallProtocolOnPartition (Device
, Index
);
666 FreePool (DevicePath
);
672 Tests to see if this driver supports a given controller. If a child device is provided,
673 it further tests to see if this driver supports creating a handle for the specified child device.
675 This function checks to see if the driver specified by This supports the device specified by
676 ControllerHandle. Drivers will typically use the device path attached to
677 ControllerHandle and/or the services from the bus I/O abstraction attached to
678 ControllerHandle to determine if the driver supports ControllerHandle. This function
679 may be called many times during platform initialization. In order to reduce boot times, the tests
680 performed by this function must be very small, and take as little time as possible to execute. This
681 function must not change the state of any hardware devices, and this function must be aware that the
682 device specified by ControllerHandle may already be managed by the same driver or a
683 different driver. This function must match its calls to AllocatePages() with FreePages(),
684 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
685 Since ControllerHandle may have been previously started by the same driver, if a protocol is
686 already in the opened state, then it must not be closed with CloseProtocol(). This is required
687 to guarantee the state of ControllerHandle is not modified by this function.
689 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
690 @param[in] ControllerHandle The handle of the controller to test. This handle
691 must support a protocol interface that supplies
692 an I/O abstraction to the driver.
693 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
694 parameter is ignored by device drivers, and is optional for bus
695 drivers. For bus drivers, if this parameter is not NULL, then
696 the bus driver must determine if the bus controller specified
697 by ControllerHandle and the child controller specified
698 by RemainingDevicePath are both supported by this
701 @retval EFI_SUCCESS The device specified by ControllerHandle and
702 RemainingDevicePath is supported by the driver specified by This.
703 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
704 RemainingDevicePath is already being managed by the driver
706 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
707 RemainingDevicePath is already being managed by a different
708 driver or an application that requires exclusive access.
709 Currently not implemented.
710 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
711 RemainingDevicePath is not supported by the driver specified by This.
715 EmmcDxeDriverBindingSupported (
716 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
717 IN EFI_HANDLE Controller
,
718 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
722 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
723 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
727 // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
729 Status
= gBS
->OpenProtocol (
731 &gEfiSdMmcPassThruProtocolGuid
,
733 This
->DriverBindingHandle
,
735 EFI_OPEN_PROTOCOL_BY_DRIVER
738 if (Status
== EFI_ALREADY_STARTED
) {
742 if (EFI_ERROR (Status
)) {
747 // Test RemainingDevicePath is valid or not.
749 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
750 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
751 if (EFI_ERROR (Status
)) {
753 // Close the I/O Abstraction(s) used to perform the supported test
757 &gEfiSdMmcPassThruProtocolGuid
,
758 This
->DriverBindingHandle
,
766 // Close the I/O Abstraction(s) used to perform the supported test
770 &gEfiSdMmcPassThruProtocolGuid
,
771 This
->DriverBindingHandle
,
776 // Open the EFI Device Path protocol needed to perform the supported test
778 Status
= gBS
->OpenProtocol (
780 &gEfiDevicePathProtocolGuid
,
781 (VOID
**) &ParentDevicePath
,
782 This
->DriverBindingHandle
,
784 EFI_OPEN_PROTOCOL_GET_PROTOCOL
790 Starts a device controller or a bus controller.
792 The Start() function is designed to be invoked from the EFI boot service ConnectController().
793 As a result, much of the error checking on the parameters to Start() has been moved into this
794 common boot service. It is legal to call Start() from other locations,
795 but the following calling restrictions must be followed or the system behavior will not be deterministic.
796 1. ControllerHandle must be a valid EFI_HANDLE.
797 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
798 EFI_DEVICE_PATH_PROTOCOL.
799 3. Prior to calling Start(), the Supported() function for the driver specified by This must
800 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
802 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
803 @param[in] ControllerHandle The handle of the controller to start. This handle
804 must support a protocol interface that supplies
805 an I/O abstraction to the driver.
806 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
807 parameter is ignored by device drivers, and is optional for bus
808 drivers. For a bus driver, if this parameter is NULL, then handles
809 for all the children of Controller are created by this driver.
810 If this parameter is not NULL and the first Device Path Node is
811 not the End of Device Path Node, then only the handle for the
812 child device specified by the first Device Path Node of
813 RemainingDevicePath is created by this driver.
814 If the first Device Path Node of RemainingDevicePath is
815 the End of Device Path Node, no child handle is created by this
818 @retval EFI_SUCCESS The device was started.
819 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
820 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
821 @retval Others The driver failded to start the device.
826 EmmcDxeDriverBindingStart (
827 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
828 IN EFI_HANDLE Controller
,
829 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
833 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
834 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
835 EMMC_DRIVER_PRIVATE_DATA
*Private
;
840 Status
= gBS
->OpenProtocol (
842 &gEfiSdMmcPassThruProtocolGuid
,
844 This
->DriverBindingHandle
,
846 EFI_OPEN_PROTOCOL_BY_DRIVER
848 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
853 // Check EFI_ALREADY_STARTED to reuse the original EMMC_DRIVER_PRIVATE_DATA.
855 if (Status
!= EFI_ALREADY_STARTED
) {
856 Private
= AllocateZeroPool (sizeof (EMMC_DRIVER_PRIVATE_DATA
));
857 if (Private
== NULL
) {
858 Status
= EFI_OUT_OF_RESOURCES
;
862 Status
= gBS
->OpenProtocol (
864 &gEfiDevicePathProtocolGuid
,
865 (VOID
**) &ParentDevicePath
,
866 This
->DriverBindingHandle
,
868 EFI_OPEN_PROTOCOL_GET_PROTOCOL
870 ASSERT_EFI_ERROR (Status
);
871 Private
->PassThru
= PassThru
;
872 Private
->Controller
= Controller
;
873 Private
->ParentDevicePath
= ParentDevicePath
;
874 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
876 Status
= gBS
->InstallProtocolInterface (
879 EFI_NATIVE_INTERFACE
,
882 if (EFI_ERROR (Status
)) {
886 Status
= gBS
->OpenProtocol (
890 This
->DriverBindingHandle
,
892 EFI_OPEN_PROTOCOL_GET_PROTOCOL
894 if (EFI_ERROR (Status
)) {
899 if (RemainingDevicePath
== NULL
) {
902 Status
= PassThru
->GetNextSlot (PassThru
, &Slot
);
903 if (EFI_ERROR (Status
)) {
905 // Cannot find more legal slots.
907 Status
= EFI_SUCCESS
;
911 Status
= DiscoverEmmcDevice (Private
, Slot
, NULL
);
912 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
916 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
917 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
918 if (!EFI_ERROR (Status
)) {
919 Status
= DiscoverEmmcDevice (Private
, Slot
, NextDevicePathNode (RemainingDevicePath
));
924 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
927 &gEfiSdMmcPassThruProtocolGuid
,
928 This
->DriverBindingHandle
,
932 if (Private
!= NULL
) {
933 gBS
->UninstallMultipleProtocolInterfaces (
946 Stops a device controller or a bus controller.
948 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
949 As a result, much of the error checking on the parameters to Stop() has been moved
950 into this common boot service. It is legal to call Stop() from other locations,
951 but the following calling restrictions must be followed or the system behavior will not be deterministic.
952 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
953 same driver's Start() function.
954 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
955 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
956 Start() function, and the Start() function must have called OpenProtocol() on
957 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
959 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
960 @param[in] ControllerHandle A handle to the device being stopped. The handle must
961 support a bus specific I/O protocol for the driver
962 to use to stop the device.
963 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
964 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
965 if NumberOfChildren is 0.
967 @retval EFI_SUCCESS The device was stopped.
968 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
973 EmmcDxeDriverBindingStop (
974 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
975 IN EFI_HANDLE Controller
,
976 IN UINTN NumberOfChildren
,
977 IN EFI_HANDLE
*ChildHandleBuffer
981 BOOLEAN AllChildrenStopped
;
983 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
984 EMMC_DRIVER_PRIVATE_DATA
*Private
;
986 EMMC_PARTITION
*Partition
;
987 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
988 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
989 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
991 LIST_ENTRY
*NextLink
;
992 EMMC_REQUEST
*Request
;
996 if (NumberOfChildren
== 0) {
997 Status
= gBS
->OpenProtocol (
1001 This
->DriverBindingHandle
,
1003 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1005 if (EFI_ERROR (Status
)) {
1006 return EFI_DEVICE_ERROR
;
1009 for (Index
= 0; Index
< EMMC_MAX_DEVICES
; Index
++) {
1010 Device
= &Private
->Device
[Index
];
1011 Status
= gBS
->OpenProtocol (
1013 &gEfiDevicePathProtocolGuid
,
1014 (VOID
**) &DevicePath
,
1015 This
->DriverBindingHandle
,
1017 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1019 if (EFI_ERROR (Status
)) {
1022 ASSERT (DevicePath
== Device
->DevicePath
);
1023 gBS
->UninstallProtocolInterface (
1025 &gEfiDevicePathProtocolGuid
,
1028 FreePool (Device
->DevicePath
);
1031 gBS
->UninstallProtocolInterface (
1036 gBS
->CloseProtocol (
1038 &gEfiSdMmcPassThruProtocolGuid
,
1039 This
->DriverBindingHandle
,
1047 AllChildrenStopped
= TRUE
;
1049 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1050 Status
= gBS
->OpenProtocol (
1051 ChildHandleBuffer
[Index
],
1052 &gEfiBlockIoProtocolGuid
,
1054 This
->DriverBindingHandle
,
1056 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1058 if (EFI_ERROR (Status
)) {
1059 Status
= gBS
->OpenProtocol (
1060 ChildHandleBuffer
[Index
],
1061 &gEfiBlockIo2ProtocolGuid
,
1062 (VOID
**) &BlockIo2
,
1063 This
->DriverBindingHandle
,
1065 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1067 if (EFI_ERROR (Status
)) {
1068 AllChildrenStopped
= FALSE
;
1073 if (BlockIo
!= NULL
) {
1074 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO (BlockIo
);
1076 ASSERT (BlockIo2
!= NULL
);
1077 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO2 (BlockIo2
);
1080 for (Link
= GetFirstNode (&Partition
->Queue
);
1081 !IsNull (&Partition
->Queue
, Link
);
1083 NextLink
= GetNextNode (&Partition
->Queue
, Link
);
1085 RemoveEntryList (Link
);
1086 Request
= EMMC_REQUEST_FROM_LINK (Link
);
1088 gBS
->CloseEvent (Request
->Event
);
1089 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
1091 if (Request
->IsEnd
) {
1092 gBS
->SignalEvent (Request
->Token
->Event
);
1099 // Close the child handle
1101 Status
= gBS
->CloseProtocol (
1103 &gEfiSdMmcPassThruProtocolGuid
,
1104 This
->DriverBindingHandle
,
1105 ChildHandleBuffer
[Index
]
1108 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1109 ChildHandleBuffer
[Index
],
1110 &gEfiDevicePathProtocolGuid
,
1111 Partition
->DevicePath
,
1112 &gEfiBlockIoProtocolGuid
,
1113 &Partition
->BlockIo
,
1114 &gEfiBlockIo2ProtocolGuid
,
1115 &Partition
->BlockIo2
,
1116 &gEfiEraseBlockProtocolGuid
,
1117 &Partition
->EraseBlock
,
1118 &gEfiDiskInfoProtocolGuid
,
1119 &Partition
->DiskInfo
,
1122 if (EFI_ERROR (Status
)) {
1123 AllChildrenStopped
= FALSE
;
1126 &gEfiSdMmcPassThruProtocolGuid
,
1127 (VOID
**)&Partition
->Device
->Private
->PassThru
,
1128 This
->DriverBindingHandle
,
1129 ChildHandleBuffer
[Index
],
1130 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1136 // If Storage Security Command Protocol is installed, then uninstall this protocol.
1138 Status
= gBS
->OpenProtocol (
1139 ChildHandleBuffer
[Index
],
1140 &gEfiStorageSecurityCommandProtocolGuid
,
1141 (VOID
**) &StorageSecurity
,
1142 This
->DriverBindingHandle
,
1144 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1147 if (!EFI_ERROR (Status
)) {
1148 Status
= gBS
->UninstallProtocolInterface (
1149 ChildHandleBuffer
[Index
],
1150 &gEfiStorageSecurityCommandProtocolGuid
,
1151 &Partition
->StorageSecurity
1153 if (EFI_ERROR (Status
)) {
1156 &gEfiSdMmcPassThruProtocolGuid
,
1157 (VOID
**) &Partition
->Device
->Private
->PassThru
,
1158 This
->DriverBindingHandle
,
1159 ChildHandleBuffer
[Index
],
1160 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1162 AllChildrenStopped
= FALSE
;
1167 FreePool (Partition
->DevicePath
);
1170 if (!AllChildrenStopped
) {
1171 return EFI_DEVICE_ERROR
;
1178 The user Entry Point for module EmmcDxe. The user code starts with this function.
1180 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1181 @param[in] SystemTable A pointer to the EFI System Table.
1183 @retval EFI_SUCCESS The entry point is executed successfully.
1184 @retval other Some errors occur when executing this entry point.
1190 IN EFI_HANDLE ImageHandle
,
1191 IN EFI_SYSTEM_TABLE
*SystemTable
1197 // Install driver model protocol(s).
1199 Status
= EfiLibInstallDriverBindingComponentName2 (
1202 &gEmmcDxeDriverBinding
,
1204 &gEmmcDxeComponentName
,
1205 &gEmmcDxeComponentName2
1207 ASSERT_EFI_ERROR (Status
);