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 - 2016, 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
79 Decode and print EMMC CSD Register content.
81 @param[in] Csd Pointer to EMMC_CSD data structure.
83 @retval EFI_SUCCESS The function completed successfully
90 DEBUG((DEBUG_INFO
, "== Dump Emmc Csd Register==\n"));
91 DEBUG((DEBUG_INFO
, " CSD structure 0x%x\n", Csd
->CsdStructure
));
92 DEBUG((DEBUG_INFO
, " System specification version 0x%x\n", Csd
->SpecVers
));
93 DEBUG((DEBUG_INFO
, " Data read access-time 1 0x%x\n", Csd
->Taac
));
94 DEBUG((DEBUG_INFO
, " Data read access-time 2 0x%x\n", Csd
->Nsac
));
95 DEBUG((DEBUG_INFO
, " Max. bus clock frequency 0x%x\n", Csd
->TranSpeed
));
96 DEBUG((DEBUG_INFO
, " Device command classes 0x%x\n", Csd
->Ccc
));
97 DEBUG((DEBUG_INFO
, " Max. read data block length 0x%x\n", Csd
->ReadBlLen
));
98 DEBUG((DEBUG_INFO
, " Partial blocks for read allowed 0x%x\n", Csd
->ReadBlPartial
));
99 DEBUG((DEBUG_INFO
, " Write block misalignment 0x%x\n", Csd
->WriteBlkMisalign
));
100 DEBUG((DEBUG_INFO
, " Read block misalignment 0x%x\n", Csd
->ReadBlkMisalign
));
101 DEBUG((DEBUG_INFO
, " DSR implemented 0x%x\n", Csd
->DsrImp
));
102 DEBUG((DEBUG_INFO
, " Device size 0x%x\n", Csd
->CSizeLow
| (Csd
->CSizeHigh
<< 2)));
103 DEBUG((DEBUG_INFO
, " Max. read current @ VDD min 0x%x\n", Csd
->VddRCurrMin
));
104 DEBUG((DEBUG_INFO
, " Max. read current @ VDD max 0x%x\n", Csd
->VddRCurrMax
));
105 DEBUG((DEBUG_INFO
, " Max. write current @ VDD min 0x%x\n", Csd
->VddWCurrMin
));
106 DEBUG((DEBUG_INFO
, " Max. write current @ VDD max 0x%x\n", Csd
->VddWCurrMax
));
107 DEBUG((DEBUG_INFO
, " Device size multiplier 0x%x\n", Csd
->CSizeMult
));
108 DEBUG((DEBUG_INFO
, " Erase group size 0x%x\n", Csd
->EraseGrpSize
));
109 DEBUG((DEBUG_INFO
, " Erase group size multiplier 0x%x\n", Csd
->EraseGrpMult
));
110 DEBUG((DEBUG_INFO
, " Write protect group size 0x%x\n", Csd
->WpGrpSize
));
111 DEBUG((DEBUG_INFO
, " Write protect group enable 0x%x\n", Csd
->WpGrpEnable
));
112 DEBUG((DEBUG_INFO
, " Manufacturer default ECC 0x%x\n", Csd
->DefaultEcc
));
113 DEBUG((DEBUG_INFO
, " Write speed factor 0x%x\n", Csd
->R2WFactor
));
114 DEBUG((DEBUG_INFO
, " Max. write data block length 0x%x\n", Csd
->WriteBlLen
));
115 DEBUG((DEBUG_INFO
, " Partial blocks for write allowed 0x%x\n", Csd
->WriteBlPartial
));
116 DEBUG((DEBUG_INFO
, " Content protection application 0x%x\n", Csd
->ContentProtApp
));
117 DEBUG((DEBUG_INFO
, " File format group 0x%x\n", Csd
->FileFormatGrp
));
118 DEBUG((DEBUG_INFO
, " Copy flag (OTP) 0x%x\n", Csd
->Copy
));
119 DEBUG((DEBUG_INFO
, " Permanent write protection 0x%x\n", Csd
->PermWriteProtect
));
120 DEBUG((DEBUG_INFO
, " Temporary write protection 0x%x\n", Csd
->TmpWriteProtect
));
121 DEBUG((DEBUG_INFO
, " File format 0x%x\n", Csd
->FileFormat
));
122 DEBUG((DEBUG_INFO
, " ECC code 0x%x\n", Csd
->Ecc
));
128 Decode and print EMMC EXT_CSD Register content.
130 @param[in] ExtCsd Pointer to the EMMC_EXT_CSD data structure.
132 @retval EFI_SUCCESS The function completed successfully
136 IN EMMC_EXT_CSD
*ExtCsd
139 DEBUG((DEBUG_INFO
, "==Dump Emmc ExtCsd Register==\n"));
140 DEBUG((DEBUG_INFO
, " Supported Command Sets 0x%x\n", ExtCsd
->CmdSet
));
141 DEBUG((DEBUG_INFO
, " HPI features 0x%x\n", ExtCsd
->HpiFeatures
));
142 DEBUG((DEBUG_INFO
, " Background operations support 0x%x\n", ExtCsd
->BkOpsSupport
));
143 DEBUG((DEBUG_INFO
, " Background operations status 0x%x\n", ExtCsd
->BkopsStatus
));
144 DEBUG((DEBUG_INFO
, " Number of correctly programmed sectors 0x%x\n", *((UINT32
*)&ExtCsd
->CorrectlyPrgSectorsNum
[0])));
145 DEBUG((DEBUG_INFO
, " Initialization time after partitioning 0x%x\n", ExtCsd
->IniTimeoutAp
));
146 DEBUG((DEBUG_INFO
, " TRIM Multiplier 0x%x\n", ExtCsd
->TrimMult
));
147 DEBUG((DEBUG_INFO
, " Secure Feature support 0x%x\n", ExtCsd
->SecFeatureSupport
));
148 DEBUG((DEBUG_INFO
, " Secure Erase Multiplier 0x%x\n", ExtCsd
->SecEraseMult
));
149 DEBUG((DEBUG_INFO
, " Secure TRIM Multiplier 0x%x\n", ExtCsd
->SecTrimMult
));
150 DEBUG((DEBUG_INFO
, " Boot information 0x%x\n", ExtCsd
->BootInfo
));
151 DEBUG((DEBUG_INFO
, " Boot partition size 0x%x\n", ExtCsd
->BootSizeMult
));
152 DEBUG((DEBUG_INFO
, " Access size 0x%x\n", ExtCsd
->AccSize
));
153 DEBUG((DEBUG_INFO
, " High-capacity erase unit size 0x%x\n", ExtCsd
->HcEraseGrpSize
));
154 DEBUG((DEBUG_INFO
, " High-capacity erase timeout 0x%x\n", ExtCsd
->EraseTimeoutMult
));
155 DEBUG((DEBUG_INFO
, " Reliable write sector count 0x%x\n", ExtCsd
->RelWrSecC
));
156 DEBUG((DEBUG_INFO
, " High-capacity write protect group size 0x%x\n", ExtCsd
->HcWpGrpSize
));
157 DEBUG((DEBUG_INFO
, " Sleep/awake timeout 0x%x\n", ExtCsd
->SATimeout
));
158 DEBUG((DEBUG_INFO
, " Sector Count 0x%x\n", *((UINT32
*)&ExtCsd
->SecCount
[0])));
159 DEBUG((DEBUG_INFO
, " Partition switching timing 0x%x\n", ExtCsd
->PartitionSwitchTime
));
160 DEBUG((DEBUG_INFO
, " Out-of-interrupt busy timing 0x%x\n", ExtCsd
->OutOfInterruptTime
));
161 DEBUG((DEBUG_INFO
, " I/O Driver Strength 0x%x\n", ExtCsd
->DriverStrength
));
162 DEBUG((DEBUG_INFO
, " Device type 0x%x\n", ExtCsd
->DeviceType
));
163 DEBUG((DEBUG_INFO
, " CSD STRUCTURE 0x%x\n", ExtCsd
->CsdStructure
));
164 DEBUG((DEBUG_INFO
, " Extended CSD revision 0x%x\n", ExtCsd
->ExtCsdRev
));
165 DEBUG((DEBUG_INFO
, " Command set 0x%x\n", ExtCsd
->CmdSet
));
166 DEBUG((DEBUG_INFO
, " Command set revision 0x%x\n", ExtCsd
->CmdSetRev
));
167 DEBUG((DEBUG_INFO
, " Power class 0x%x\n", ExtCsd
->PowerClass
));
168 DEBUG((DEBUG_INFO
, " High-speed interface timing 0x%x\n", ExtCsd
->HsTiming
));
169 DEBUG((DEBUG_INFO
, " Bus width mode 0x%x\n", ExtCsd
->BusWidth
));
170 DEBUG((DEBUG_INFO
, " Erased memory content 0x%x\n", ExtCsd
->ErasedMemCont
));
171 DEBUG((DEBUG_INFO
, " Partition configuration 0x%x\n", ExtCsd
->PartitionConfig
));
172 DEBUG((DEBUG_INFO
, " Boot config protection 0x%x\n", ExtCsd
->BootConfigProt
));
173 DEBUG((DEBUG_INFO
, " Boot bus Conditions 0x%x\n", ExtCsd
->BootBusConditions
));
174 DEBUG((DEBUG_INFO
, " High-density erase group definition 0x%x\n", ExtCsd
->EraseGroupDef
));
175 DEBUG((DEBUG_INFO
, " Boot write protection status register 0x%x\n", ExtCsd
->BootWpStatus
));
176 DEBUG((DEBUG_INFO
, " Boot area write protection register 0x%x\n", ExtCsd
->BootWp
));
177 DEBUG((DEBUG_INFO
, " User area write protection register 0x%x\n", ExtCsd
->UserWp
));
178 DEBUG((DEBUG_INFO
, " FW configuration 0x%x\n", ExtCsd
->FwConfig
));
179 DEBUG((DEBUG_INFO
, " RPMB Size 0x%x\n", ExtCsd
->RpmbSizeMult
));
180 DEBUG((DEBUG_INFO
, " H/W reset function 0x%x\n", ExtCsd
->RstFunction
));
181 DEBUG((DEBUG_INFO
, " Partitioning Support 0x%x\n", ExtCsd
->PartitioningSupport
));
182 DEBUG((DEBUG_INFO
, " Max Enhanced Area Size 0x%02x%02x%02x\n", \
183 ExtCsd
->MaxEnhSizeMult
[2], ExtCsd
->MaxEnhSizeMult
[1], ExtCsd
->MaxEnhSizeMult
[0]));
184 DEBUG((DEBUG_INFO
, " Partitions attribute 0x%x\n", ExtCsd
->PartitionsAttribute
));
185 DEBUG((DEBUG_INFO
, " Partitioning Setting 0x%x\n", ExtCsd
->PartitionSettingCompleted
));
186 DEBUG((DEBUG_INFO
, " General Purpose Partition 1 Size 0x%02x%02x%02x\n", \
187 ExtCsd
->GpSizeMult
[2], ExtCsd
->GpSizeMult
[1], ExtCsd
->GpSizeMult
[0]));
188 DEBUG((DEBUG_INFO
, " General Purpose Partition 2 Size 0x%02x%02x%02x\n", \
189 ExtCsd
->GpSizeMult
[5], ExtCsd
->GpSizeMult
[4], ExtCsd
->GpSizeMult
[3]));
190 DEBUG((DEBUG_INFO
, " General Purpose Partition 3 Size 0x%02x%02x%02x\n", \
191 ExtCsd
->GpSizeMult
[8], ExtCsd
->GpSizeMult
[7], ExtCsd
->GpSizeMult
[6]));
192 DEBUG((DEBUG_INFO
, " General Purpose Partition 4 Size 0x%02x%02x%02x\n", \
193 ExtCsd
->GpSizeMult
[11], ExtCsd
->GpSizeMult
[10], ExtCsd
->GpSizeMult
[9]));
194 DEBUG((DEBUG_INFO
, " Enhanced User Data Area Size 0x%02x%02x%02x\n", \
195 ExtCsd
->EnhSizeMult
[2], ExtCsd
->EnhSizeMult
[1], ExtCsd
->EnhSizeMult
[0]));
196 DEBUG((DEBUG_INFO
, " Enhanced User Data Start Address 0x%x\n", *((UINT32
*)&ExtCsd
->EnhStartAddr
[0])));
197 DEBUG((DEBUG_INFO
, " Bad Block Management mode 0x%x\n", ExtCsd
->SecBadBlkMgmnt
));
198 DEBUG((DEBUG_INFO
, " Native sector size 0x%x\n", ExtCsd
->NativeSectorSize
));
199 DEBUG((DEBUG_INFO
, " Sector size emulation 0x%x\n", ExtCsd
->UseNativeSector
));
200 DEBUG((DEBUG_INFO
, " Sector size 0x%x\n", ExtCsd
->DataSectorSize
));
206 Get EMMC device model name.
208 @param[in, out] Device The pointer to the EMMC_DEVICE data structure.
209 @param[in] Cid Pointer to EMMC_CID data structure.
211 @retval EFI_SUCCESS The function completed successfully
216 IN OUT EMMC_DEVICE
*Device
,
220 CHAR8 String
[EMMC_MODEL_NAME_MAX_LEN
];
222 ZeroMem (String
, sizeof (String
));
223 CopyMem (String
, &Cid
->OemId
, sizeof (Cid
->OemId
));
224 String
[sizeof (Cid
->OemId
)] = ' ';
225 CopyMem (String
+ sizeof (Cid
->OemId
) + 1, Cid
->ProductName
, sizeof (Cid
->ProductName
));
226 String
[sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
)] = ' ';
227 CopyMem (String
+ sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
) + 1, Cid
->ProductSerialNumber
, sizeof (Cid
->ProductSerialNumber
));
229 AsciiStrToUnicodeStr (String
, Device
->ModelName
);
235 Discover all partitions in the EMMC device.
237 @param[in] Device The pointer to the EMMC_DEVICE data structure.
239 @retval EFI_SUCCESS All the partitions in the device are successfully enumerated.
240 @return Others Some error occurs when enumerating the partitions.
244 DiscoverAllPartitions (
245 IN EMMC_DEVICE
*Device
249 EMMC_PARTITION
*Partition
;
252 EMMC_EXT_CSD
*ExtCsd
;
262 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
263 if (EFI_ERROR (Status
)) {
267 // Deselect the device to force it enter stby mode before getting CSD
269 // Note here we don't judge return status as some EMMC devices return
270 // error but the state has been stby.
272 EmmcSelect (Device
, 0);
274 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
275 if (EFI_ERROR (Status
)) {
280 Status
= EmmcGetCsd (Device
, Slot
+ 1, Csd
);
281 if (EFI_ERROR (Status
)) {
286 if ((Csd
->CSizeLow
| Csd
->CSizeHigh
<< 2) == 0xFFF) {
287 Device
->SectorAddressing
= TRUE
;
289 Device
->SectorAddressing
= FALSE
;
293 Status
= EmmcGetCid (Device
, Slot
+ 1, Cid
);
294 if (EFI_ERROR (Status
)) {
298 Status
= EmmcSelect (Device
, Slot
+ 1);
299 if (EFI_ERROR (Status
)) {
303 ExtCsd
= &Device
->ExtCsd
;
304 Status
= EmmcGetExtCsd (Device
, ExtCsd
);
305 if (EFI_ERROR (Status
)) {
310 if (ExtCsd
->ExtCsdRev
< 5) {
311 DEBUG ((EFI_D_ERROR
, "The EMMC device version is too low, we don't support!!!\n"));
312 return EFI_UNSUPPORTED
;
315 if ((ExtCsd
->PartitioningSupport
& BIT0
) != BIT0
) {
316 DEBUG ((EFI_D_ERROR
, "The EMMC device doesn't support Partition Feature!!!\n"));
317 return EFI_UNSUPPORTED
;
320 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
321 Partition
= &Device
->Partition
[Index
];
322 CopyMem (Partition
, &mEmmcPartitionTemplate
, sizeof (EMMC_PARTITION
));
323 Partition
->Device
= Device
;
324 InitializeListHead (&Partition
->Queue
);
325 Partition
->BlockIo
.Media
= &Partition
->BlockMedia
;
326 Partition
->BlockIo2
.Media
= &Partition
->BlockMedia
;
327 Partition
->PartitionType
= Index
;
328 Partition
->BlockMedia
.IoAlign
= Device
->Private
->PassThru
->IoAlign
;
329 Partition
->BlockMedia
.BlockSize
= 0x200;
330 Partition
->BlockMedia
.LastBlock
= 0x00;
331 Partition
->BlockMedia
.RemovableMedia
= FALSE
;
332 Partition
->BlockMedia
.MediaPresent
= TRUE
;
333 Partition
->BlockMedia
.LogicalPartition
= FALSE
;
336 case EmmcPartitionUserData
:
337 SecCount
= *(UINT32
*)&ExtCsd
->SecCount
;
338 Capacity
= MultU64x32 ((UINT64
) SecCount
, 0x200);
340 case EmmcPartitionBoot1
:
341 case EmmcPartitionBoot2
:
342 Capacity
= ExtCsd
->BootSizeMult
* SIZE_128KB
;
344 case EmmcPartitionRPMB
:
345 Capacity
= ExtCsd
->RpmbSizeMult
* SIZE_128KB
;
347 case EmmcPartitionGP1
:
348 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[0] | (ExtCsd
->GpSizeMult
[1] << 8) | (ExtCsd
->GpSizeMult
[2] << 16));
349 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
351 case EmmcPartitionGP2
:
352 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[3] | (ExtCsd
->GpSizeMult
[4] << 8) | (ExtCsd
->GpSizeMult
[5] << 16));
353 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
355 case EmmcPartitionGP3
:
356 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[6] | (ExtCsd
->GpSizeMult
[7] << 8) | (ExtCsd
->GpSizeMult
[8] << 16));
357 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
359 case EmmcPartitionGP4
:
360 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[9] | (ExtCsd
->GpSizeMult
[10] << 8) | (ExtCsd
->GpSizeMult
[11] << 16));
361 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
365 return EFI_INVALID_PARAMETER
;
369 Partition
->Enable
= TRUE
;
370 Partition
->BlockMedia
.LastBlock
= DivU64x32 (Capacity
, Partition
->BlockMedia
.BlockSize
) - 1;
378 Install BlkIo, BlkIo2 and Ssp protocols for the specified partition in the EMMC device.
380 @param[in] Device The pointer to the EMMC_DEVICE data structure.
381 @param[in] Index The index of the partition.
383 @retval EFI_SUCCESS The protocols are installed successfully.
384 @retval Others Some error occurs when installing the protocols.
388 InstallProtocolOnPartition (
389 IN EMMC_DEVICE
*Device
,
394 EMMC_PARTITION
*Partition
;
395 CONTROLLER_DEVICE_PATH ControlNode
;
396 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
397 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
398 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
399 EFI_HANDLE DeviceHandle
;
404 ParentDevicePath
= Device
->DevicePath
;
406 ControlNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
407 ControlNode
.Header
.SubType
= HW_CONTROLLER_DP
;
408 SetDevicePathNodeLength (&ControlNode
.Header
, sizeof (CONTROLLER_DEVICE_PATH
));
409 ControlNode
.ControllerNumber
= Index
;
411 DevicePath
= AppendDevicePathNode (ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&ControlNode
);
412 if (DevicePath
== NULL
) {
413 Status
= EFI_OUT_OF_RESOURCES
;
418 RemainingDevicePath
= DevicePath
;
419 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
420 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
421 Status
= EFI_ALREADY_STARTED
;
425 Partition
= &Device
->Partition
[Index
];
426 Partition
->DevicePath
= DevicePath
;
427 if (Partition
->Enable
) {
429 // Install BlkIo/BlkIo2/Ssp for the specified partition
431 Status
= gBS
->InstallMultipleProtocolInterfaces (
433 &gEfiDevicePathProtocolGuid
,
434 Partition
->DevicePath
,
435 &gEfiBlockIoProtocolGuid
,
437 &gEfiBlockIo2ProtocolGuid
,
438 &Partition
->BlockIo2
,
441 if (EFI_ERROR (Status
)) {
445 if (((Partition
->PartitionType
== EmmcPartitionUserData
) ||
446 (Partition
->PartitionType
== EmmcPartitionBoot1
) ||
447 (Partition
->PartitionType
== EmmcPartitionBoot2
)) &&
448 ((Device
->Csd
.Ccc
& BIT10
) != 0)) {
449 Status
= gBS
->InstallProtocolInterface (
451 &gEfiStorageSecurityCommandProtocolGuid
,
452 EFI_NATIVE_INTERFACE
,
453 &Partition
->StorageSecurity
455 if (EFI_ERROR (Status
)) {
456 gBS
->UninstallMultipleProtocolInterfaces (
458 &gEfiDevicePathProtocolGuid
,
459 Partition
->DevicePath
,
460 &gEfiBlockIoProtocolGuid
,
462 &gEfiBlockIo2ProtocolGuid
,
463 &Partition
->BlockIo2
,
471 Device
->Private
->Controller
,
472 &gEfiSdMmcPassThruProtocolGuid
,
473 (VOID
**) &(Device
->Private
->PassThru
),
474 Device
->Private
->DriverBindingHandle
,
476 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
479 Status
= EFI_INVALID_PARAMETER
;
483 if (EFI_ERROR (Status
) && (DevicePath
!= NULL
)) {
484 FreePool (DevicePath
);
491 Scan EMMC Bus to discover the device.
493 @param[in] Private The EMMC driver private data structure.
494 @param[in] Slot The slot number to check device present.
496 @retval EFI_SUCCESS Successfully to discover the device and attach
497 SdMmcIoProtocol to it.
498 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
500 @retval EFI_ALREADY_STARTED The device was discovered before.
501 @retval Others Fail to discover the device.
507 IN EMMC_DRIVER_PRIVATE_DATA
*Private
,
509 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
514 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
515 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
516 EFI_DEVICE_PATH_PROTOCOL
*RemainingEmmcDevPath
;
518 EFI_HANDLE DeviceHandle
;
519 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
524 NewDevicePath
= NULL
;
525 RemainingDevicePath
= NULL
;
526 PassThru
= Private
->PassThru
;
527 Device
= &Private
->Device
[Slot
];
530 // Build Device Path to check if the EMMC device present at the slot.
532 Status
= PassThru
->BuildDevicePath (
537 if (EFI_ERROR(Status
)) {
541 if (DevicePath
->SubType
!= MSG_EMMC_DP
) {
542 Status
= EFI_UNSUPPORTED
;
546 NewDevicePath
= AppendDevicePathNode (
547 Private
->ParentDevicePath
,
550 if (NewDevicePath
== NULL
) {
551 Status
= EFI_OUT_OF_RESOURCES
;
556 RemainingEmmcDevPath
= NewDevicePath
;
557 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingEmmcDevPath
, &DeviceHandle
);
559 // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized.
561 if (EFI_ERROR (Status
) || (DeviceHandle
== NULL
) || !IsDevicePathEnd (RemainingEmmcDevPath
)) {
562 Device
->DevicePath
= NewDevicePath
;
564 Device
->Private
= Private
;
566 // Expose user area in the Sd memory card to upper layer.
568 Status
= DiscoverAllPartitions (Device
);
569 if (EFI_ERROR(Status
)) {
570 FreePool (NewDevicePath
);
574 Status
= gBS
->InstallProtocolInterface (
576 &gEfiDevicePathProtocolGuid
,
577 EFI_NATIVE_INTERFACE
,
580 if (EFI_ERROR(Status
)) {
581 FreePool (NewDevicePath
);
585 Device
->ControllerNameTable
= NULL
;
586 GetEmmcModelName (Device
, &Device
->Cid
);
589 gEmmcDxeComponentName
.SupportedLanguages
,
590 &Device
->ControllerNameTable
,
596 gEmmcDxeComponentName
.SupportedLanguages
,
597 &Device
->ControllerNameTable
,
603 if (RemainingDevicePath
== NULL
) {
605 // Expose all partitions in the Emmc device to upper layer.
607 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
608 InstallProtocolOnPartition (Device
, Index
);
610 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
612 // Enumerate the specified partition
614 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
615 if ((DevicePathType (&Node
->DevPath
) != HARDWARE_DEVICE_PATH
) ||
616 (DevicePathSubType (&Node
->DevPath
) != HW_CONTROLLER_DP
) ||
617 (DevicePathNodeLength (&Node
->DevPath
) != sizeof (CONTROLLER_DEVICE_PATH
))) {
618 Status
= EFI_INVALID_PARAMETER
;
622 Index
= (UINT8
)Node
->Controller
.ControllerNumber
;
623 if (Index
>= EMMC_MAX_PARTITIONS
) {
624 Status
= EFI_INVALID_PARAMETER
;
628 Status
= InstallProtocolOnPartition (Device
, Index
);
632 FreePool (DevicePath
);
638 Tests to see if this driver supports a given controller. If a child device is provided,
639 it further tests to see if this driver supports creating a handle for the specified child device.
641 This function checks to see if the driver specified by This supports the device specified by
642 ControllerHandle. Drivers will typically use the device path attached to
643 ControllerHandle and/or the services from the bus I/O abstraction attached to
644 ControllerHandle to determine if the driver supports ControllerHandle. This function
645 may be called many times during platform initialization. In order to reduce boot times, the tests
646 performed by this function must be very small, and take as little time as possible to execute. This
647 function must not change the state of any hardware devices, and this function must be aware that the
648 device specified by ControllerHandle may already be managed by the same driver or a
649 different driver. This function must match its calls to AllocatePages() with FreePages(),
650 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
651 Since ControllerHandle may have been previously started by the same driver, if a protocol is
652 already in the opened state, then it must not be closed with CloseProtocol(). This is required
653 to guarantee the state of ControllerHandle is not modified by this function.
655 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
656 @param[in] ControllerHandle The handle of the controller to test. This handle
657 must support a protocol interface that supplies
658 an I/O abstraction to the driver.
659 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
660 parameter is ignored by device drivers, and is optional for bus
661 drivers. For bus drivers, if this parameter is not NULL, then
662 the bus driver must determine if the bus controller specified
663 by ControllerHandle and the child controller specified
664 by RemainingDevicePath are both supported by this
667 @retval EFI_SUCCESS The device specified by ControllerHandle and
668 RemainingDevicePath is supported by the driver specified by This.
669 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
670 RemainingDevicePath is already being managed by the driver
672 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
673 RemainingDevicePath is already being managed by a different
674 driver or an application that requires exclusive access.
675 Currently not implemented.
676 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
677 RemainingDevicePath is not supported by the driver specified by This.
681 EmmcDxeDriverBindingSupported (
682 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
683 IN EFI_HANDLE Controller
,
684 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
688 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
689 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
693 // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
695 Status
= gBS
->OpenProtocol (
697 &gEfiSdMmcPassThruProtocolGuid
,
699 This
->DriverBindingHandle
,
701 EFI_OPEN_PROTOCOL_BY_DRIVER
704 if (Status
== EFI_ALREADY_STARTED
) {
708 if (EFI_ERROR (Status
)) {
713 // Test RemainingDevicePath is valid or not.
715 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
716 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
717 if (EFI_ERROR (Status
)) {
719 // Close the I/O Abstraction(s) used to perform the supported test
723 &gEfiSdMmcPassThruProtocolGuid
,
724 This
->DriverBindingHandle
,
732 // Close the I/O Abstraction(s) used to perform the supported test
736 &gEfiSdMmcPassThruProtocolGuid
,
737 This
->DriverBindingHandle
,
742 // Open the EFI Device Path protocol needed to perform the supported test
744 Status
= gBS
->OpenProtocol (
746 &gEfiDevicePathProtocolGuid
,
747 (VOID
**) &ParentDevicePath
,
748 This
->DriverBindingHandle
,
750 EFI_OPEN_PROTOCOL_GET_PROTOCOL
756 Starts a device controller or a bus controller.
758 The Start() function is designed to be invoked from the EFI boot service ConnectController().
759 As a result, much of the error checking on the parameters to Start() has been moved into this
760 common boot service. It is legal to call Start() from other locations,
761 but the following calling restrictions must be followed or the system behavior will not be deterministic.
762 1. ControllerHandle must be a valid EFI_HANDLE.
763 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
764 EFI_DEVICE_PATH_PROTOCOL.
765 3. Prior to calling Start(), the Supported() function for the driver specified by This must
766 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
768 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
769 @param[in] ControllerHandle The handle of the controller to start. This handle
770 must support a protocol interface that supplies
771 an I/O abstraction to the driver.
772 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
773 parameter is ignored by device drivers, and is optional for bus
774 drivers. For a bus driver, if this parameter is NULL, then handles
775 for all the children of Controller are created by this driver.
776 If this parameter is not NULL and the first Device Path Node is
777 not the End of Device Path Node, then only the handle for the
778 child device specified by the first Device Path Node of
779 RemainingDevicePath is created by this driver.
780 If the first Device Path Node of RemainingDevicePath is
781 the End of Device Path Node, no child handle is created by this
784 @retval EFI_SUCCESS The device was started.
785 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
786 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
787 @retval Others The driver failded to start the device.
792 EmmcDxeDriverBindingStart (
793 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
794 IN EFI_HANDLE Controller
,
795 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
799 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
800 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
801 EMMC_DRIVER_PRIVATE_DATA
*Private
;
806 Status
= gBS
->OpenProtocol (
808 &gEfiSdMmcPassThruProtocolGuid
,
810 This
->DriverBindingHandle
,
812 EFI_OPEN_PROTOCOL_BY_DRIVER
814 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
819 // Check EFI_ALREADY_STARTED to reuse the original EMMC_DRIVER_PRIVATE_DATA.
821 if (Status
!= EFI_ALREADY_STARTED
) {
822 Private
= AllocateZeroPool (sizeof (EMMC_DRIVER_PRIVATE_DATA
));
823 if (Private
== NULL
) {
824 Status
= EFI_OUT_OF_RESOURCES
;
828 Status
= gBS
->OpenProtocol (
830 &gEfiDevicePathProtocolGuid
,
831 (VOID
**) &ParentDevicePath
,
832 This
->DriverBindingHandle
,
834 EFI_OPEN_PROTOCOL_GET_PROTOCOL
836 ASSERT_EFI_ERROR (Status
);
837 Private
->PassThru
= PassThru
;
838 Private
->Controller
= Controller
;
839 Private
->ParentDevicePath
= ParentDevicePath
;
840 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
842 Status
= gBS
->InstallProtocolInterface (
845 EFI_NATIVE_INTERFACE
,
848 if (EFI_ERROR (Status
)) {
852 Status
= gBS
->OpenProtocol (
856 This
->DriverBindingHandle
,
858 EFI_OPEN_PROTOCOL_GET_PROTOCOL
860 if (EFI_ERROR (Status
)) {
865 if (RemainingDevicePath
== NULL
) {
868 Status
= PassThru
->GetNextSlot (PassThru
, &Slot
);
869 if (EFI_ERROR (Status
)) {
871 // Cannot find more legal slots.
873 Status
= EFI_SUCCESS
;
877 Status
= DiscoverEmmcDevice (Private
, Slot
, NULL
);
878 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
882 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
883 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
884 if (!EFI_ERROR (Status
)) {
885 Status
= DiscoverEmmcDevice (Private
, Slot
, NextDevicePathNode (RemainingDevicePath
));
890 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
893 &gEfiSdMmcPassThruProtocolGuid
,
894 This
->DriverBindingHandle
,
898 if (Private
!= NULL
) {
899 gBS
->UninstallMultipleProtocolInterfaces (
912 Stops a device controller or a bus controller.
914 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
915 As a result, much of the error checking on the parameters to Stop() has been moved
916 into this common boot service. It is legal to call Stop() from other locations,
917 but the following calling restrictions must be followed or the system behavior will not be deterministic.
918 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
919 same driver's Start() function.
920 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
921 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
922 Start() function, and the Start() function must have called OpenProtocol() on
923 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
925 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
926 @param[in] ControllerHandle A handle to the device being stopped. The handle must
927 support a bus specific I/O protocol for the driver
928 to use to stop the device.
929 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
930 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
931 if NumberOfChildren is 0.
933 @retval EFI_SUCCESS The device was stopped.
934 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
939 EmmcDxeDriverBindingStop (
940 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
941 IN EFI_HANDLE Controller
,
942 IN UINTN NumberOfChildren
,
943 IN EFI_HANDLE
*ChildHandleBuffer
947 BOOLEAN AllChildrenStopped
;
949 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
950 EMMC_DRIVER_PRIVATE_DATA
*Private
;
952 EMMC_PARTITION
*Partition
;
953 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
954 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
955 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
957 LIST_ENTRY
*NextLink
;
958 EMMC_REQUEST
*Request
;
962 if (NumberOfChildren
== 0) {
963 Status
= gBS
->OpenProtocol (
967 This
->DriverBindingHandle
,
969 EFI_OPEN_PROTOCOL_GET_PROTOCOL
971 if (EFI_ERROR (Status
)) {
972 return EFI_DEVICE_ERROR
;
975 for (Index
= 0; Index
< EMMC_MAX_DEVICES
; Index
++) {
976 Device
= &Private
->Device
[Index
];
977 Status
= gBS
->OpenProtocol (
979 &gEfiDevicePathProtocolGuid
,
980 (VOID
**) &DevicePath
,
981 This
->DriverBindingHandle
,
983 EFI_OPEN_PROTOCOL_GET_PROTOCOL
985 if (EFI_ERROR (Status
)) {
988 ASSERT (DevicePath
== Device
->DevicePath
);
989 gBS
->UninstallProtocolInterface (
991 &gEfiDevicePathProtocolGuid
,
994 FreePool (Device
->DevicePath
);
997 gBS
->UninstallProtocolInterface (
1002 gBS
->CloseProtocol (
1004 &gEfiSdMmcPassThruProtocolGuid
,
1005 This
->DriverBindingHandle
,
1013 AllChildrenStopped
= TRUE
;
1015 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1016 Status
= gBS
->OpenProtocol (
1017 ChildHandleBuffer
[Index
],
1018 &gEfiBlockIoProtocolGuid
,
1020 This
->DriverBindingHandle
,
1022 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1024 if (EFI_ERROR (Status
)) {
1025 Status
= gBS
->OpenProtocol (
1026 ChildHandleBuffer
[Index
],
1027 &gEfiBlockIo2ProtocolGuid
,
1028 (VOID
**) &BlockIo2
,
1029 This
->DriverBindingHandle
,
1031 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1033 if (EFI_ERROR (Status
)) {
1034 AllChildrenStopped
= FALSE
;
1039 if (BlockIo
!= NULL
) {
1040 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO (BlockIo
);
1042 ASSERT (BlockIo2
!= NULL
);
1043 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO2 (BlockIo2
);
1046 for (Link
= GetFirstNode (&Partition
->Queue
);
1047 !IsNull (&Partition
->Queue
, Link
);
1049 NextLink
= GetNextNode (&Partition
->Queue
, Link
);
1051 RemoveEntryList (Link
);
1052 Request
= EMMC_REQUEST_FROM_LINK (Link
);
1054 gBS
->CloseEvent (Request
->Event
);
1055 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
1057 if (Request
->IsEnd
) {
1058 gBS
->SignalEvent (Request
->Token
->Event
);
1065 // Close the child handle
1067 Status
= gBS
->CloseProtocol (
1069 &gEfiSdMmcPassThruProtocolGuid
,
1070 This
->DriverBindingHandle
,
1071 ChildHandleBuffer
[Index
]
1074 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1075 ChildHandleBuffer
[Index
],
1076 &gEfiDevicePathProtocolGuid
,
1077 Partition
->DevicePath
,
1078 &gEfiBlockIoProtocolGuid
,
1079 &Partition
->BlockIo
,
1080 &gEfiBlockIo2ProtocolGuid
,
1081 &Partition
->BlockIo2
,
1084 if (EFI_ERROR (Status
)) {
1085 AllChildrenStopped
= FALSE
;
1088 &gEfiSdMmcPassThruProtocolGuid
,
1089 (VOID
**)&Partition
->Device
->Private
->PassThru
,
1090 This
->DriverBindingHandle
,
1091 ChildHandleBuffer
[Index
],
1092 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1098 // If Storage Security Command Protocol is installed, then uninstall this protocol.
1100 Status
= gBS
->OpenProtocol (
1101 ChildHandleBuffer
[Index
],
1102 &gEfiStorageSecurityCommandProtocolGuid
,
1103 (VOID
**) &StorageSecurity
,
1104 This
->DriverBindingHandle
,
1106 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1109 if (!EFI_ERROR (Status
)) {
1110 Status
= gBS
->UninstallProtocolInterface (
1111 ChildHandleBuffer
[Index
],
1112 &gEfiStorageSecurityCommandProtocolGuid
,
1113 &Partition
->StorageSecurity
1115 if (EFI_ERROR (Status
)) {
1118 &gEfiSdMmcPassThruProtocolGuid
,
1119 (VOID
**) &Partition
->Device
->Private
->PassThru
,
1120 This
->DriverBindingHandle
,
1121 ChildHandleBuffer
[Index
],
1122 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1124 AllChildrenStopped
= FALSE
;
1129 FreePool (Partition
->DevicePath
);
1132 if (!AllChildrenStopped
) {
1133 return EFI_DEVICE_ERROR
;
1140 The user Entry Point for module EmmcDxe. The user code starts with this function.
1142 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1143 @param[in] SystemTable A pointer to the EFI System Table.
1145 @retval EFI_SUCCESS The entry point is executed successfully.
1146 @retval other Some errors occur when executing this entry point.
1152 IN EFI_HANDLE ImageHandle
,
1153 IN EFI_SYSTEM_TABLE
*SystemTable
1159 // Install driver model protocol(s).
1161 Status
= EfiLibInstallDriverBindingComponentName2 (
1164 &gEmmcDxeDriverBinding
,
1166 &gEmmcDxeComponentName
,
1167 &gEmmcDxeComponentName2
1169 ASSERT_EFI_ERROR (Status
);