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
72 EFI_ERASE_BLOCK_PROTOCOL_REVISION
,
84 Decode and print EMMC CSD Register content.
86 @param[in] Csd Pointer to EMMC_CSD data structure.
88 @retval EFI_SUCCESS The function completed successfully
95 DEBUG((DEBUG_INFO
, "== Dump Emmc Csd Register==\n"));
96 DEBUG((DEBUG_INFO
, " CSD structure 0x%x\n", Csd
->CsdStructure
));
97 DEBUG((DEBUG_INFO
, " System specification version 0x%x\n", Csd
->SpecVers
));
98 DEBUG((DEBUG_INFO
, " Data read access-time 1 0x%x\n", Csd
->Taac
));
99 DEBUG((DEBUG_INFO
, " Data read access-time 2 0x%x\n", Csd
->Nsac
));
100 DEBUG((DEBUG_INFO
, " Max. bus clock frequency 0x%x\n", Csd
->TranSpeed
));
101 DEBUG((DEBUG_INFO
, " Device command classes 0x%x\n", Csd
->Ccc
));
102 DEBUG((DEBUG_INFO
, " Max. read data block length 0x%x\n", Csd
->ReadBlLen
));
103 DEBUG((DEBUG_INFO
, " Partial blocks for read allowed 0x%x\n", Csd
->ReadBlPartial
));
104 DEBUG((DEBUG_INFO
, " Write block misalignment 0x%x\n", Csd
->WriteBlkMisalign
));
105 DEBUG((DEBUG_INFO
, " Read block misalignment 0x%x\n", Csd
->ReadBlkMisalign
));
106 DEBUG((DEBUG_INFO
, " DSR implemented 0x%x\n", Csd
->DsrImp
));
107 DEBUG((DEBUG_INFO
, " Device size 0x%x\n", Csd
->CSizeLow
| (Csd
->CSizeHigh
<< 2)));
108 DEBUG((DEBUG_INFO
, " Max. read current @ VDD min 0x%x\n", Csd
->VddRCurrMin
));
109 DEBUG((DEBUG_INFO
, " Max. read current @ VDD max 0x%x\n", Csd
->VddRCurrMax
));
110 DEBUG((DEBUG_INFO
, " Max. write current @ VDD min 0x%x\n", Csd
->VddWCurrMin
));
111 DEBUG((DEBUG_INFO
, " Max. write current @ VDD max 0x%x\n", Csd
->VddWCurrMax
));
112 DEBUG((DEBUG_INFO
, " Device size multiplier 0x%x\n", Csd
->CSizeMult
));
113 DEBUG((DEBUG_INFO
, " Erase group size 0x%x\n", Csd
->EraseGrpSize
));
114 DEBUG((DEBUG_INFO
, " Erase group size multiplier 0x%x\n", Csd
->EraseGrpMult
));
115 DEBUG((DEBUG_INFO
, " Write protect group size 0x%x\n", Csd
->WpGrpSize
));
116 DEBUG((DEBUG_INFO
, " Write protect group enable 0x%x\n", Csd
->WpGrpEnable
));
117 DEBUG((DEBUG_INFO
, " Manufacturer default ECC 0x%x\n", Csd
->DefaultEcc
));
118 DEBUG((DEBUG_INFO
, " Write speed factor 0x%x\n", Csd
->R2WFactor
));
119 DEBUG((DEBUG_INFO
, " Max. write data block length 0x%x\n", Csd
->WriteBlLen
));
120 DEBUG((DEBUG_INFO
, " Partial blocks for write allowed 0x%x\n", Csd
->WriteBlPartial
));
121 DEBUG((DEBUG_INFO
, " Content protection application 0x%x\n", Csd
->ContentProtApp
));
122 DEBUG((DEBUG_INFO
, " File format group 0x%x\n", Csd
->FileFormatGrp
));
123 DEBUG((DEBUG_INFO
, " Copy flag (OTP) 0x%x\n", Csd
->Copy
));
124 DEBUG((DEBUG_INFO
, " Permanent write protection 0x%x\n", Csd
->PermWriteProtect
));
125 DEBUG((DEBUG_INFO
, " Temporary write protection 0x%x\n", Csd
->TmpWriteProtect
));
126 DEBUG((DEBUG_INFO
, " File format 0x%x\n", Csd
->FileFormat
));
127 DEBUG((DEBUG_INFO
, " ECC code 0x%x\n", Csd
->Ecc
));
133 Decode and print EMMC EXT_CSD Register content.
135 @param[in] ExtCsd Pointer to the EMMC_EXT_CSD data structure.
137 @retval EFI_SUCCESS The function completed successfully
141 IN EMMC_EXT_CSD
*ExtCsd
144 DEBUG((DEBUG_INFO
, "==Dump Emmc ExtCsd Register==\n"));
145 DEBUG((DEBUG_INFO
, " Supported Command Sets 0x%x\n", ExtCsd
->CmdSet
));
146 DEBUG((DEBUG_INFO
, " HPI features 0x%x\n", ExtCsd
->HpiFeatures
));
147 DEBUG((DEBUG_INFO
, " Background operations support 0x%x\n", ExtCsd
->BkOpsSupport
));
148 DEBUG((DEBUG_INFO
, " Background operations status 0x%x\n", ExtCsd
->BkopsStatus
));
149 DEBUG((DEBUG_INFO
, " Number of correctly programmed sectors 0x%x\n", *((UINT32
*)&ExtCsd
->CorrectlyPrgSectorsNum
[0])));
150 DEBUG((DEBUG_INFO
, " Initialization time after partitioning 0x%x\n", ExtCsd
->IniTimeoutAp
));
151 DEBUG((DEBUG_INFO
, " TRIM Multiplier 0x%x\n", ExtCsd
->TrimMult
));
152 DEBUG((DEBUG_INFO
, " Secure Feature support 0x%x\n", ExtCsd
->SecFeatureSupport
));
153 DEBUG((DEBUG_INFO
, " Secure Erase Multiplier 0x%x\n", ExtCsd
->SecEraseMult
));
154 DEBUG((DEBUG_INFO
, " Secure TRIM Multiplier 0x%x\n", ExtCsd
->SecTrimMult
));
155 DEBUG((DEBUG_INFO
, " Boot information 0x%x\n", ExtCsd
->BootInfo
));
156 DEBUG((DEBUG_INFO
, " Boot partition size 0x%x\n", ExtCsd
->BootSizeMult
));
157 DEBUG((DEBUG_INFO
, " Access size 0x%x\n", ExtCsd
->AccSize
));
158 DEBUG((DEBUG_INFO
, " High-capacity erase unit size 0x%x\n", ExtCsd
->HcEraseGrpSize
));
159 DEBUG((DEBUG_INFO
, " High-capacity erase timeout 0x%x\n", ExtCsd
->EraseTimeoutMult
));
160 DEBUG((DEBUG_INFO
, " Reliable write sector count 0x%x\n", ExtCsd
->RelWrSecC
));
161 DEBUG((DEBUG_INFO
, " High-capacity write protect group size 0x%x\n", ExtCsd
->HcWpGrpSize
));
162 DEBUG((DEBUG_INFO
, " Sleep/awake timeout 0x%x\n", ExtCsd
->SATimeout
));
163 DEBUG((DEBUG_INFO
, " Sector Count 0x%x\n", *((UINT32
*)&ExtCsd
->SecCount
[0])));
164 DEBUG((DEBUG_INFO
, " Partition switching timing 0x%x\n", ExtCsd
->PartitionSwitchTime
));
165 DEBUG((DEBUG_INFO
, " Out-of-interrupt busy timing 0x%x\n", ExtCsd
->OutOfInterruptTime
));
166 DEBUG((DEBUG_INFO
, " I/O Driver Strength 0x%x\n", ExtCsd
->DriverStrength
));
167 DEBUG((DEBUG_INFO
, " Device type 0x%x\n", ExtCsd
->DeviceType
));
168 DEBUG((DEBUG_INFO
, " CSD STRUCTURE 0x%x\n", ExtCsd
->CsdStructure
));
169 DEBUG((DEBUG_INFO
, " Extended CSD revision 0x%x\n", ExtCsd
->ExtCsdRev
));
170 DEBUG((DEBUG_INFO
, " Command set 0x%x\n", ExtCsd
->CmdSet
));
171 DEBUG((DEBUG_INFO
, " Command set revision 0x%x\n", ExtCsd
->CmdSetRev
));
172 DEBUG((DEBUG_INFO
, " Power class 0x%x\n", ExtCsd
->PowerClass
));
173 DEBUG((DEBUG_INFO
, " High-speed interface timing 0x%x\n", ExtCsd
->HsTiming
));
174 DEBUG((DEBUG_INFO
, " Bus width mode 0x%x\n", ExtCsd
->BusWidth
));
175 DEBUG((DEBUG_INFO
, " Erased memory content 0x%x\n", ExtCsd
->ErasedMemCont
));
176 DEBUG((DEBUG_INFO
, " Partition configuration 0x%x\n", ExtCsd
->PartitionConfig
));
177 DEBUG((DEBUG_INFO
, " Boot config protection 0x%x\n", ExtCsd
->BootConfigProt
));
178 DEBUG((DEBUG_INFO
, " Boot bus Conditions 0x%x\n", ExtCsd
->BootBusConditions
));
179 DEBUG((DEBUG_INFO
, " High-density erase group definition 0x%x\n", ExtCsd
->EraseGroupDef
));
180 DEBUG((DEBUG_INFO
, " Boot write protection status register 0x%x\n", ExtCsd
->BootWpStatus
));
181 DEBUG((DEBUG_INFO
, " Boot area write protection register 0x%x\n", ExtCsd
->BootWp
));
182 DEBUG((DEBUG_INFO
, " User area write protection register 0x%x\n", ExtCsd
->UserWp
));
183 DEBUG((DEBUG_INFO
, " FW configuration 0x%x\n", ExtCsd
->FwConfig
));
184 DEBUG((DEBUG_INFO
, " RPMB Size 0x%x\n", ExtCsd
->RpmbSizeMult
));
185 DEBUG((DEBUG_INFO
, " H/W reset function 0x%x\n", ExtCsd
->RstFunction
));
186 DEBUG((DEBUG_INFO
, " Partitioning Support 0x%x\n", ExtCsd
->PartitioningSupport
));
187 DEBUG((DEBUG_INFO
, " Max Enhanced Area Size 0x%02x%02x%02x\n", \
188 ExtCsd
->MaxEnhSizeMult
[2], ExtCsd
->MaxEnhSizeMult
[1], ExtCsd
->MaxEnhSizeMult
[0]));
189 DEBUG((DEBUG_INFO
, " Partitions attribute 0x%x\n", ExtCsd
->PartitionsAttribute
));
190 DEBUG((DEBUG_INFO
, " Partitioning Setting 0x%x\n", ExtCsd
->PartitionSettingCompleted
));
191 DEBUG((DEBUG_INFO
, " General Purpose Partition 1 Size 0x%02x%02x%02x\n", \
192 ExtCsd
->GpSizeMult
[2], ExtCsd
->GpSizeMult
[1], ExtCsd
->GpSizeMult
[0]));
193 DEBUG((DEBUG_INFO
, " General Purpose Partition 2 Size 0x%02x%02x%02x\n", \
194 ExtCsd
->GpSizeMult
[5], ExtCsd
->GpSizeMult
[4], ExtCsd
->GpSizeMult
[3]));
195 DEBUG((DEBUG_INFO
, " General Purpose Partition 3 Size 0x%02x%02x%02x\n", \
196 ExtCsd
->GpSizeMult
[8], ExtCsd
->GpSizeMult
[7], ExtCsd
->GpSizeMult
[6]));
197 DEBUG((DEBUG_INFO
, " General Purpose Partition 4 Size 0x%02x%02x%02x\n", \
198 ExtCsd
->GpSizeMult
[11], ExtCsd
->GpSizeMult
[10], ExtCsd
->GpSizeMult
[9]));
199 DEBUG((DEBUG_INFO
, " Enhanced User Data Area Size 0x%02x%02x%02x\n", \
200 ExtCsd
->EnhSizeMult
[2], ExtCsd
->EnhSizeMult
[1], ExtCsd
->EnhSizeMult
[0]));
201 DEBUG((DEBUG_INFO
, " Enhanced User Data Start Address 0x%x\n", *((UINT32
*)&ExtCsd
->EnhStartAddr
[0])));
202 DEBUG((DEBUG_INFO
, " Bad Block Management mode 0x%x\n", ExtCsd
->SecBadBlkMgmnt
));
203 DEBUG((DEBUG_INFO
, " Native sector size 0x%x\n", ExtCsd
->NativeSectorSize
));
204 DEBUG((DEBUG_INFO
, " Sector size emulation 0x%x\n", ExtCsd
->UseNativeSector
));
205 DEBUG((DEBUG_INFO
, " Sector size 0x%x\n", ExtCsd
->DataSectorSize
));
211 Get EMMC device model name.
213 @param[in, out] Device The pointer to the EMMC_DEVICE data structure.
214 @param[in] Cid Pointer to EMMC_CID data structure.
216 @retval EFI_SUCCESS The function completed successfully
221 IN OUT EMMC_DEVICE
*Device
,
225 CHAR8 String
[EMMC_MODEL_NAME_MAX_LEN
];
227 ZeroMem (String
, sizeof (String
));
228 CopyMem (String
, &Cid
->OemId
, sizeof (Cid
->OemId
));
229 String
[sizeof (Cid
->OemId
)] = ' ';
230 CopyMem (String
+ sizeof (Cid
->OemId
) + 1, Cid
->ProductName
, sizeof (Cid
->ProductName
));
231 String
[sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
)] = ' ';
232 CopyMem (String
+ sizeof (Cid
->OemId
) + sizeof (Cid
->ProductName
) + 1, Cid
->ProductSerialNumber
, sizeof (Cid
->ProductSerialNumber
));
234 AsciiStrToUnicodeStrS (String
, Device
->ModelName
, sizeof (Device
->ModelName
) / sizeof (Device
->ModelName
[0]));
240 Discover all partitions in the EMMC device.
242 @param[in] Device The pointer to the EMMC_DEVICE data structure.
244 @retval EFI_SUCCESS All the partitions in the device are successfully enumerated.
245 @return Others Some error occurs when enumerating the partitions.
249 DiscoverAllPartitions (
250 IN EMMC_DEVICE
*Device
254 EMMC_PARTITION
*Partition
;
257 EMMC_EXT_CSD
*ExtCsd
;
267 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
268 if (EFI_ERROR (Status
)) {
272 // Deselect the device to force it enter stby mode before getting CSD
274 // Note here we don't judge return status as some EMMC devices return
275 // error but the state has been stby.
277 EmmcSelect (Device
, 0);
279 Status
= EmmcSendStatus (Device
, Slot
+ 1, &DevStatus
);
280 if (EFI_ERROR (Status
)) {
285 Status
= EmmcGetCsd (Device
, Slot
+ 1, Csd
);
286 if (EFI_ERROR (Status
)) {
291 if ((Csd
->CSizeLow
| Csd
->CSizeHigh
<< 2) == 0xFFF) {
292 Device
->SectorAddressing
= TRUE
;
294 Device
->SectorAddressing
= FALSE
;
298 Status
= EmmcGetCid (Device
, Slot
+ 1, Cid
);
299 if (EFI_ERROR (Status
)) {
303 Status
= EmmcSelect (Device
, Slot
+ 1);
304 if (EFI_ERROR (Status
)) {
308 ExtCsd
= &Device
->ExtCsd
;
309 Status
= EmmcGetExtCsd (Device
, ExtCsd
);
310 if (EFI_ERROR (Status
)) {
315 if (ExtCsd
->ExtCsdRev
< 5) {
316 DEBUG ((EFI_D_ERROR
, "The EMMC device version is too low, we don't support!!!\n"));
317 return EFI_UNSUPPORTED
;
320 if ((ExtCsd
->PartitioningSupport
& BIT0
) != BIT0
) {
321 DEBUG ((EFI_D_ERROR
, "The EMMC device doesn't support Partition Feature!!!\n"));
322 return EFI_UNSUPPORTED
;
325 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
326 Partition
= &Device
->Partition
[Index
];
327 CopyMem (Partition
, &mEmmcPartitionTemplate
, sizeof (EMMC_PARTITION
));
328 Partition
->Device
= Device
;
329 InitializeListHead (&Partition
->Queue
);
330 Partition
->BlockIo
.Media
= &Partition
->BlockMedia
;
331 Partition
->BlockIo2
.Media
= &Partition
->BlockMedia
;
332 Partition
->PartitionType
= Index
;
333 Partition
->BlockMedia
.IoAlign
= Device
->Private
->PassThru
->IoAlign
;
334 Partition
->BlockMedia
.BlockSize
= 0x200;
335 Partition
->BlockMedia
.LastBlock
= 0x00;
336 Partition
->BlockMedia
.RemovableMedia
= FALSE
;
337 Partition
->BlockMedia
.MediaPresent
= TRUE
;
338 Partition
->BlockMedia
.LogicalPartition
= FALSE
;
341 case EmmcPartitionUserData
:
342 SecCount
= *(UINT32
*)&ExtCsd
->SecCount
;
343 Capacity
= MultU64x32 ((UINT64
) SecCount
, 0x200);
345 case EmmcPartitionBoot1
:
346 case EmmcPartitionBoot2
:
347 Capacity
= ExtCsd
->BootSizeMult
* SIZE_128KB
;
349 case EmmcPartitionRPMB
:
350 Capacity
= ExtCsd
->RpmbSizeMult
* SIZE_128KB
;
352 case EmmcPartitionGP1
:
353 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[0] | (ExtCsd
->GpSizeMult
[1] << 8) | (ExtCsd
->GpSizeMult
[2] << 16));
354 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
356 case EmmcPartitionGP2
:
357 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[3] | (ExtCsd
->GpSizeMult
[4] << 8) | (ExtCsd
->GpSizeMult
[5] << 16));
358 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
360 case EmmcPartitionGP3
:
361 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[6] | (ExtCsd
->GpSizeMult
[7] << 8) | (ExtCsd
->GpSizeMult
[8] << 16));
362 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
364 case EmmcPartitionGP4
:
365 GpSizeMult
= (UINT32
)(ExtCsd
->GpSizeMult
[9] | (ExtCsd
->GpSizeMult
[10] << 8) | (ExtCsd
->GpSizeMult
[11] << 16));
366 Capacity
= MultU64x32 (MultU64x32 (MultU64x32 ((UINT64
)GpSizeMult
, ExtCsd
->HcWpGrpSize
), ExtCsd
->HcEraseGrpSize
), SIZE_512KB
);
370 return EFI_INVALID_PARAMETER
;
374 Partition
->Enable
= TRUE
;
375 Partition
->BlockMedia
.LastBlock
= DivU64x32 (Capacity
, Partition
->BlockMedia
.BlockSize
) - 1;
378 if ((ExtCsd
->EraseGroupDef
& BIT0
) == 0) {
379 if (Csd
->WriteBlLen
< 9) {
380 Partition
->EraseBlock
.EraseLengthGranularity
= 1;
382 Partition
->EraseBlock
.EraseLengthGranularity
= (Csd
->EraseGrpMult
+ 1) * (Csd
->EraseGrpSize
+ 1) * (1 << (Csd
->WriteBlLen
- 9));
385 Partition
->EraseBlock
.EraseLengthGranularity
= 1024 * ExtCsd
->HcEraseGrpSize
;
393 Install BlkIo, BlkIo2 and Ssp protocols for the specified partition in the EMMC device.
395 @param[in] Device The pointer to the EMMC_DEVICE data structure.
396 @param[in] Index The index of the partition.
398 @retval EFI_SUCCESS The protocols are installed successfully.
399 @retval Others Some error occurs when installing the protocols.
403 InstallProtocolOnPartition (
404 IN EMMC_DEVICE
*Device
,
409 EMMC_PARTITION
*Partition
;
410 CONTROLLER_DEVICE_PATH ControlNode
;
411 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
412 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
413 EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
;
414 EFI_HANDLE DeviceHandle
;
419 ParentDevicePath
= Device
->DevicePath
;
421 ControlNode
.Header
.Type
= HARDWARE_DEVICE_PATH
;
422 ControlNode
.Header
.SubType
= HW_CONTROLLER_DP
;
423 SetDevicePathNodeLength (&ControlNode
.Header
, sizeof (CONTROLLER_DEVICE_PATH
));
424 ControlNode
.ControllerNumber
= Index
;
426 DevicePath
= AppendDevicePathNode (ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*)&ControlNode
);
427 if (DevicePath
== NULL
) {
428 Status
= EFI_OUT_OF_RESOURCES
;
433 RemainingDevicePath
= DevicePath
;
434 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingDevicePath
, &DeviceHandle
);
435 if (!EFI_ERROR (Status
) && (DeviceHandle
!= NULL
) && IsDevicePathEnd(RemainingDevicePath
)) {
436 Status
= EFI_ALREADY_STARTED
;
440 Partition
= &Device
->Partition
[Index
];
441 Partition
->DevicePath
= DevicePath
;
442 if (Partition
->Enable
) {
444 // Install BlkIo/BlkIo2/Ssp for the specified partition
446 if (Partition
->PartitionType
!= EmmcPartitionRPMB
) {
447 Status
= gBS
->InstallMultipleProtocolInterfaces (
449 &gEfiDevicePathProtocolGuid
,
450 Partition
->DevicePath
,
451 &gEfiBlockIoProtocolGuid
,
453 &gEfiBlockIo2ProtocolGuid
,
454 &Partition
->BlockIo2
,
455 &gEfiEraseBlockProtocolGuid
,
456 &Partition
->EraseBlock
,
459 if (EFI_ERROR (Status
)) {
463 if (((Partition
->PartitionType
== EmmcPartitionUserData
) ||
464 (Partition
->PartitionType
== EmmcPartitionBoot1
) ||
465 (Partition
->PartitionType
== EmmcPartitionBoot2
)) &&
466 ((Device
->Csd
.Ccc
& BIT10
) != 0)) {
467 Status
= gBS
->InstallProtocolInterface (
469 &gEfiStorageSecurityCommandProtocolGuid
,
470 EFI_NATIVE_INTERFACE
,
471 &Partition
->StorageSecurity
473 if (EFI_ERROR (Status
)) {
474 gBS
->UninstallMultipleProtocolInterfaces (
476 &gEfiDevicePathProtocolGuid
,
477 Partition
->DevicePath
,
478 &gEfiBlockIoProtocolGuid
,
480 &gEfiBlockIo2ProtocolGuid
,
481 &Partition
->BlockIo2
,
482 &gEfiEraseBlockProtocolGuid
,
483 &Partition
->EraseBlock
,
491 Device
->Private
->Controller
,
492 &gEfiSdMmcPassThruProtocolGuid
,
493 (VOID
**) &(Device
->Private
->PassThru
),
494 Device
->Private
->DriverBindingHandle
,
496 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
501 Status
= EFI_INVALID_PARAMETER
;
505 if (EFI_ERROR (Status
) && (DevicePath
!= NULL
)) {
506 FreePool (DevicePath
);
513 Scan EMMC Bus to discover the device.
515 @param[in] Private The EMMC driver private data structure.
516 @param[in] Slot The slot number to check device present.
517 @param[in] RemainingDevicePath The pointer to the remaining device path.
519 @retval EFI_SUCCESS Successfully to discover the device and attach
520 SdMmcIoProtocol to it.
521 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
523 @retval EFI_ALREADY_STARTED The device was discovered before.
524 @retval Others Fail to discover the device.
530 IN EMMC_DRIVER_PRIVATE_DATA
*Private
,
532 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
537 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
538 EFI_DEVICE_PATH_PROTOCOL
*NewDevicePath
;
539 EFI_DEVICE_PATH_PROTOCOL
*RemainingEmmcDevPath
;
541 EFI_HANDLE DeviceHandle
;
542 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
547 NewDevicePath
= NULL
;
548 RemainingDevicePath
= NULL
;
549 PassThru
= Private
->PassThru
;
550 Device
= &Private
->Device
[Slot
];
553 // Build Device Path to check if the EMMC device present at the slot.
555 Status
= PassThru
->BuildDevicePath (
560 if (EFI_ERROR(Status
)) {
564 if (DevicePath
->SubType
!= MSG_EMMC_DP
) {
565 Status
= EFI_UNSUPPORTED
;
569 NewDevicePath
= AppendDevicePathNode (
570 Private
->ParentDevicePath
,
573 if (NewDevicePath
== NULL
) {
574 Status
= EFI_OUT_OF_RESOURCES
;
579 RemainingEmmcDevPath
= NewDevicePath
;
580 Status
= gBS
->LocateDevicePath (&gEfiDevicePathProtocolGuid
, &RemainingEmmcDevPath
, &DeviceHandle
);
582 // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized.
584 if (EFI_ERROR (Status
) || (DeviceHandle
== NULL
) || !IsDevicePathEnd (RemainingEmmcDevPath
)) {
585 Device
->DevicePath
= NewDevicePath
;
587 Device
->Private
= Private
;
589 // Expose user area in the Sd memory card to upper layer.
591 Status
= DiscoverAllPartitions (Device
);
592 if (EFI_ERROR(Status
)) {
593 FreePool (NewDevicePath
);
597 Status
= gBS
->InstallProtocolInterface (
599 &gEfiDevicePathProtocolGuid
,
600 EFI_NATIVE_INTERFACE
,
603 if (EFI_ERROR(Status
)) {
604 FreePool (NewDevicePath
);
608 Device
->ControllerNameTable
= NULL
;
609 GetEmmcModelName (Device
, &Device
->Cid
);
612 gEmmcDxeComponentName
.SupportedLanguages
,
613 &Device
->ControllerNameTable
,
619 gEmmcDxeComponentName
.SupportedLanguages
,
620 &Device
->ControllerNameTable
,
626 if (RemainingDevicePath
== NULL
) {
628 // Expose all partitions in the Emmc device to upper layer.
630 for (Index
= 0; Index
< EMMC_MAX_PARTITIONS
; Index
++) {
631 InstallProtocolOnPartition (Device
, Index
);
633 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
635 // Enumerate the specified partition
637 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
638 if ((DevicePathType (&Node
->DevPath
) != HARDWARE_DEVICE_PATH
) ||
639 (DevicePathSubType (&Node
->DevPath
) != HW_CONTROLLER_DP
) ||
640 (DevicePathNodeLength (&Node
->DevPath
) != sizeof (CONTROLLER_DEVICE_PATH
))) {
641 Status
= EFI_INVALID_PARAMETER
;
645 Index
= (UINT8
)Node
->Controller
.ControllerNumber
;
646 if (Index
>= EMMC_MAX_PARTITIONS
) {
647 Status
= EFI_INVALID_PARAMETER
;
651 Status
= InstallProtocolOnPartition (Device
, Index
);
655 FreePool (DevicePath
);
661 Tests to see if this driver supports a given controller. If a child device is provided,
662 it further tests to see if this driver supports creating a handle for the specified child device.
664 This function checks to see if the driver specified by This supports the device specified by
665 ControllerHandle. Drivers will typically use the device path attached to
666 ControllerHandle and/or the services from the bus I/O abstraction attached to
667 ControllerHandle to determine if the driver supports ControllerHandle. This function
668 may be called many times during platform initialization. In order to reduce boot times, the tests
669 performed by this function must be very small, and take as little time as possible to execute. This
670 function must not change the state of any hardware devices, and this function must be aware that the
671 device specified by ControllerHandle may already be managed by the same driver or a
672 different driver. This function must match its calls to AllocatePages() with FreePages(),
673 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
674 Since ControllerHandle may have been previously started by the same driver, if a protocol is
675 already in the opened state, then it must not be closed with CloseProtocol(). This is required
676 to guarantee the state of ControllerHandle is not modified by this function.
678 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
679 @param[in] ControllerHandle The handle of the controller to test. This handle
680 must support a protocol interface that supplies
681 an I/O abstraction to the driver.
682 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
683 parameter is ignored by device drivers, and is optional for bus
684 drivers. For bus drivers, if this parameter is not NULL, then
685 the bus driver must determine if the bus controller specified
686 by ControllerHandle and the child controller specified
687 by RemainingDevicePath are both supported by this
690 @retval EFI_SUCCESS The device specified by ControllerHandle and
691 RemainingDevicePath is supported by the driver specified by This.
692 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
693 RemainingDevicePath is already being managed by the driver
695 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
696 RemainingDevicePath is already being managed by a different
697 driver or an application that requires exclusive access.
698 Currently not implemented.
699 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
700 RemainingDevicePath is not supported by the driver specified by This.
704 EmmcDxeDriverBindingSupported (
705 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
706 IN EFI_HANDLE Controller
,
707 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
711 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
712 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
716 // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
718 Status
= gBS
->OpenProtocol (
720 &gEfiSdMmcPassThruProtocolGuid
,
722 This
->DriverBindingHandle
,
724 EFI_OPEN_PROTOCOL_BY_DRIVER
727 if (Status
== EFI_ALREADY_STARTED
) {
731 if (EFI_ERROR (Status
)) {
736 // Test RemainingDevicePath is valid or not.
738 if ((RemainingDevicePath
!= NULL
) && !IsDevicePathEnd (RemainingDevicePath
)) {
739 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
740 if (EFI_ERROR (Status
)) {
742 // Close the I/O Abstraction(s) used to perform the supported test
746 &gEfiSdMmcPassThruProtocolGuid
,
747 This
->DriverBindingHandle
,
755 // Close the I/O Abstraction(s) used to perform the supported test
759 &gEfiSdMmcPassThruProtocolGuid
,
760 This
->DriverBindingHandle
,
765 // Open the EFI Device Path protocol needed to perform the supported test
767 Status
= gBS
->OpenProtocol (
769 &gEfiDevicePathProtocolGuid
,
770 (VOID
**) &ParentDevicePath
,
771 This
->DriverBindingHandle
,
773 EFI_OPEN_PROTOCOL_GET_PROTOCOL
779 Starts a device controller or a bus controller.
781 The Start() function is designed to be invoked from the EFI boot service ConnectController().
782 As a result, much of the error checking on the parameters to Start() has been moved into this
783 common boot service. It is legal to call Start() from other locations,
784 but the following calling restrictions must be followed or the system behavior will not be deterministic.
785 1. ControllerHandle must be a valid EFI_HANDLE.
786 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
787 EFI_DEVICE_PATH_PROTOCOL.
788 3. Prior to calling Start(), the Supported() function for the driver specified by This must
789 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
791 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
792 @param[in] ControllerHandle The handle of the controller to start. This handle
793 must support a protocol interface that supplies
794 an I/O abstraction to the driver.
795 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
796 parameter is ignored by device drivers, and is optional for bus
797 drivers. For a bus driver, if this parameter is NULL, then handles
798 for all the children of Controller are created by this driver.
799 If this parameter is not NULL and the first Device Path Node is
800 not the End of Device Path Node, then only the handle for the
801 child device specified by the first Device Path Node of
802 RemainingDevicePath is created by this driver.
803 If the first Device Path Node of RemainingDevicePath is
804 the End of Device Path Node, no child handle is created by this
807 @retval EFI_SUCCESS The device was started.
808 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
809 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
810 @retval Others The driver failded to start the device.
815 EmmcDxeDriverBindingStart (
816 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
817 IN EFI_HANDLE Controller
,
818 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
822 EFI_SD_MMC_PASS_THRU_PROTOCOL
*PassThru
;
823 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
824 EMMC_DRIVER_PRIVATE_DATA
*Private
;
829 Status
= gBS
->OpenProtocol (
831 &gEfiSdMmcPassThruProtocolGuid
,
833 This
->DriverBindingHandle
,
835 EFI_OPEN_PROTOCOL_BY_DRIVER
837 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
842 // Check EFI_ALREADY_STARTED to reuse the original EMMC_DRIVER_PRIVATE_DATA.
844 if (Status
!= EFI_ALREADY_STARTED
) {
845 Private
= AllocateZeroPool (sizeof (EMMC_DRIVER_PRIVATE_DATA
));
846 if (Private
== NULL
) {
847 Status
= EFI_OUT_OF_RESOURCES
;
851 Status
= gBS
->OpenProtocol (
853 &gEfiDevicePathProtocolGuid
,
854 (VOID
**) &ParentDevicePath
,
855 This
->DriverBindingHandle
,
857 EFI_OPEN_PROTOCOL_GET_PROTOCOL
859 ASSERT_EFI_ERROR (Status
);
860 Private
->PassThru
= PassThru
;
861 Private
->Controller
= Controller
;
862 Private
->ParentDevicePath
= ParentDevicePath
;
863 Private
->DriverBindingHandle
= This
->DriverBindingHandle
;
865 Status
= gBS
->InstallProtocolInterface (
868 EFI_NATIVE_INTERFACE
,
871 if (EFI_ERROR (Status
)) {
875 Status
= gBS
->OpenProtocol (
879 This
->DriverBindingHandle
,
881 EFI_OPEN_PROTOCOL_GET_PROTOCOL
883 if (EFI_ERROR (Status
)) {
888 if (RemainingDevicePath
== NULL
) {
891 Status
= PassThru
->GetNextSlot (PassThru
, &Slot
);
892 if (EFI_ERROR (Status
)) {
894 // Cannot find more legal slots.
896 Status
= EFI_SUCCESS
;
900 Status
= DiscoverEmmcDevice (Private
, Slot
, NULL
);
901 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
905 } else if (!IsDevicePathEnd (RemainingDevicePath
)) {
906 Status
= PassThru
->GetSlotNumber (PassThru
, RemainingDevicePath
, &Slot
);
907 if (!EFI_ERROR (Status
)) {
908 Status
= DiscoverEmmcDevice (Private
, Slot
, NextDevicePathNode (RemainingDevicePath
));
913 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
916 &gEfiSdMmcPassThruProtocolGuid
,
917 This
->DriverBindingHandle
,
921 if (Private
!= NULL
) {
922 gBS
->UninstallMultipleProtocolInterfaces (
935 Stops a device controller or a bus controller.
937 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
938 As a result, much of the error checking on the parameters to Stop() has been moved
939 into this common boot service. It is legal to call Stop() from other locations,
940 but the following calling restrictions must be followed or the system behavior will not be deterministic.
941 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
942 same driver's Start() function.
943 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
944 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
945 Start() function, and the Start() function must have called OpenProtocol() on
946 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
948 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
949 @param[in] ControllerHandle A handle to the device being stopped. The handle must
950 support a bus specific I/O protocol for the driver
951 to use to stop the device.
952 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
953 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
954 if NumberOfChildren is 0.
956 @retval EFI_SUCCESS The device was stopped.
957 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
962 EmmcDxeDriverBindingStop (
963 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
964 IN EFI_HANDLE Controller
,
965 IN UINTN NumberOfChildren
,
966 IN EFI_HANDLE
*ChildHandleBuffer
970 BOOLEAN AllChildrenStopped
;
972 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
973 EMMC_DRIVER_PRIVATE_DATA
*Private
;
975 EMMC_PARTITION
*Partition
;
976 EFI_BLOCK_IO_PROTOCOL
*BlockIo
;
977 EFI_BLOCK_IO2_PROTOCOL
*BlockIo2
;
978 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL
*StorageSecurity
;
980 LIST_ENTRY
*NextLink
;
981 EMMC_REQUEST
*Request
;
985 if (NumberOfChildren
== 0) {
986 Status
= gBS
->OpenProtocol (
990 This
->DriverBindingHandle
,
992 EFI_OPEN_PROTOCOL_GET_PROTOCOL
994 if (EFI_ERROR (Status
)) {
995 return EFI_DEVICE_ERROR
;
998 for (Index
= 0; Index
< EMMC_MAX_DEVICES
; Index
++) {
999 Device
= &Private
->Device
[Index
];
1000 Status
= gBS
->OpenProtocol (
1002 &gEfiDevicePathProtocolGuid
,
1003 (VOID
**) &DevicePath
,
1004 This
->DriverBindingHandle
,
1006 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1008 if (EFI_ERROR (Status
)) {
1011 ASSERT (DevicePath
== Device
->DevicePath
);
1012 gBS
->UninstallProtocolInterface (
1014 &gEfiDevicePathProtocolGuid
,
1017 FreePool (Device
->DevicePath
);
1020 gBS
->UninstallProtocolInterface (
1025 gBS
->CloseProtocol (
1027 &gEfiSdMmcPassThruProtocolGuid
,
1028 This
->DriverBindingHandle
,
1036 AllChildrenStopped
= TRUE
;
1038 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
1039 Status
= gBS
->OpenProtocol (
1040 ChildHandleBuffer
[Index
],
1041 &gEfiBlockIoProtocolGuid
,
1043 This
->DriverBindingHandle
,
1045 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1047 if (EFI_ERROR (Status
)) {
1048 Status
= gBS
->OpenProtocol (
1049 ChildHandleBuffer
[Index
],
1050 &gEfiBlockIo2ProtocolGuid
,
1051 (VOID
**) &BlockIo2
,
1052 This
->DriverBindingHandle
,
1054 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1056 if (EFI_ERROR (Status
)) {
1057 AllChildrenStopped
= FALSE
;
1062 if (BlockIo
!= NULL
) {
1063 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO (BlockIo
);
1065 ASSERT (BlockIo2
!= NULL
);
1066 Partition
= EMMC_PARTITION_DATA_FROM_BLKIO2 (BlockIo2
);
1069 for (Link
= GetFirstNode (&Partition
->Queue
);
1070 !IsNull (&Partition
->Queue
, Link
);
1072 NextLink
= GetNextNode (&Partition
->Queue
, Link
);
1074 RemoveEntryList (Link
);
1075 Request
= EMMC_REQUEST_FROM_LINK (Link
);
1077 gBS
->CloseEvent (Request
->Event
);
1078 Request
->Token
->TransactionStatus
= EFI_ABORTED
;
1080 if (Request
->IsEnd
) {
1081 gBS
->SignalEvent (Request
->Token
->Event
);
1088 // Close the child handle
1090 Status
= gBS
->CloseProtocol (
1092 &gEfiSdMmcPassThruProtocolGuid
,
1093 This
->DriverBindingHandle
,
1094 ChildHandleBuffer
[Index
]
1097 Status
= gBS
->UninstallMultipleProtocolInterfaces (
1098 ChildHandleBuffer
[Index
],
1099 &gEfiDevicePathProtocolGuid
,
1100 Partition
->DevicePath
,
1101 &gEfiBlockIoProtocolGuid
,
1102 &Partition
->BlockIo
,
1103 &gEfiBlockIo2ProtocolGuid
,
1104 &Partition
->BlockIo2
,
1105 &gEfiEraseBlockProtocolGuid
,
1106 &Partition
->EraseBlock
,
1109 if (EFI_ERROR (Status
)) {
1110 AllChildrenStopped
= FALSE
;
1113 &gEfiSdMmcPassThruProtocolGuid
,
1114 (VOID
**)&Partition
->Device
->Private
->PassThru
,
1115 This
->DriverBindingHandle
,
1116 ChildHandleBuffer
[Index
],
1117 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1123 // If Storage Security Command Protocol is installed, then uninstall this protocol.
1125 Status
= gBS
->OpenProtocol (
1126 ChildHandleBuffer
[Index
],
1127 &gEfiStorageSecurityCommandProtocolGuid
,
1128 (VOID
**) &StorageSecurity
,
1129 This
->DriverBindingHandle
,
1131 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1134 if (!EFI_ERROR (Status
)) {
1135 Status
= gBS
->UninstallProtocolInterface (
1136 ChildHandleBuffer
[Index
],
1137 &gEfiStorageSecurityCommandProtocolGuid
,
1138 &Partition
->StorageSecurity
1140 if (EFI_ERROR (Status
)) {
1143 &gEfiSdMmcPassThruProtocolGuid
,
1144 (VOID
**) &Partition
->Device
->Private
->PassThru
,
1145 This
->DriverBindingHandle
,
1146 ChildHandleBuffer
[Index
],
1147 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1149 AllChildrenStopped
= FALSE
;
1154 FreePool (Partition
->DevicePath
);
1157 if (!AllChildrenStopped
) {
1158 return EFI_DEVICE_ERROR
;
1165 The user Entry Point for module EmmcDxe. The user code starts with this function.
1167 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1168 @param[in] SystemTable A pointer to the EFI System Table.
1170 @retval EFI_SUCCESS The entry point is executed successfully.
1171 @retval other Some errors occur when executing this entry point.
1177 IN EFI_HANDLE ImageHandle
,
1178 IN EFI_SYSTEM_TABLE
*SystemTable
1184 // Install driver model protocol(s).
1186 Status
= EfiLibInstallDriverBindingComponentName2 (
1189 &gEmmcDxeDriverBinding
,
1191 &gEmmcDxeComponentName
,
1192 &gEmmcDxeComponentName2
1194 ASSERT_EFI_ERROR (Status
);