]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
Merge branch 'master' of https://github.com/tianocore/edk2
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / EmmcDxe / EmmcDxe.c
1 /** @file
2 The EmmcDxe driver is used to manage the EMMC device.
3
4 It produces BlockIo, BlockIo2 and StorageSecurity protocols to allow upper layer
5 access the EMMC device.
6
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
12
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.
15
16 **/
17
18 #include "EmmcDxe.h"
19
20 //
21 // EmmcDxe Driver Binding Protocol Instance
22 //
23 EFI_DRIVER_BINDING_PROTOCOL gEmmcDxeDriverBinding = {
24 EmmcDxeDriverBindingSupported,
25 EmmcDxeDriverBindingStart,
26 EmmcDxeDriverBindingStop,
27 0x10,
28 NULL,
29 NULL
30 };
31
32 //
33 // Template for Emmc Partitions.
34 //
35 EMMC_PARTITION mEmmcPartitionTemplate = {
36 EMMC_PARTITION_SIGNATURE, // Signature
37 FALSE, // Enable
38 EmmcPartitionUnknown, // PartitionType
39 NULL, // Handle
40 NULL, // DevicePath
41 { // BlockIo
42 EFI_BLOCK_IO_PROTOCOL_REVISION,
43 NULL,
44 EmmcReset,
45 EmmcReadBlocks,
46 EmmcWriteBlocks,
47 EmmcFlushBlocks
48 },
49 { // BlockIo2
50 NULL,
51 EmmcResetEx,
52 EmmcReadBlocksEx,
53 EmmcWriteBlocksEx,
54 EmmcFlushBlocksEx
55 },
56 { // BlockMedia
57 0, // MediaId
58 FALSE, // RemovableMedia
59 TRUE, // MediaPresent
60 FALSE, // LogicPartition
61 FALSE, // ReadOnly
62 FALSE, // WritingCache
63 0x200, // BlockSize
64 0, // IoAlign
65 0 // LastBlock
66 },
67 { // StorageSecurity
68 EmmcSecurityProtocolIn,
69 EmmcSecurityProtocolOut
70 },
71 { // EraseBlock
72 EFI_ERASE_BLOCK_PROTOCOL_REVISION,
73 1,
74 EmmcEraseBlocks
75 },
76 {
77 NULL,
78 NULL
79 },
80 NULL // Device
81 };
82
83 /**
84 Decode and print EMMC CSD Register content.
85
86 @param[in] Csd Pointer to EMMC_CSD data structure.
87
88 @retval EFI_SUCCESS The function completed successfully
89 **/
90 EFI_STATUS
91 DumpCsd (
92 IN EMMC_CSD *Csd
93 )
94 {
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));
128
129 return EFI_SUCCESS;
130 }
131
132 /**
133 Decode and print EMMC EXT_CSD Register content.
134
135 @param[in] ExtCsd Pointer to the EMMC_EXT_CSD data structure.
136
137 @retval EFI_SUCCESS The function completed successfully
138 **/
139 EFI_STATUS
140 DumpExtCsd (
141 IN EMMC_EXT_CSD *ExtCsd
142 )
143 {
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));
206
207 return EFI_SUCCESS;
208 }
209
210 /**
211 Get EMMC device model name.
212
213 @param[in, out] Device The pointer to the EMMC_DEVICE data structure.
214 @param[in] Cid Pointer to EMMC_CID data structure.
215
216 @retval EFI_SUCCESS The function completed successfully
217
218 **/
219 EFI_STATUS
220 GetEmmcModelName (
221 IN OUT EMMC_DEVICE *Device,
222 IN EMMC_CID *Cid
223 )
224 {
225 CHAR8 String[EMMC_MODEL_NAME_MAX_LEN];
226
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));
233
234 AsciiStrToUnicodeStrS (String, Device->ModelName, sizeof (Device->ModelName) / sizeof (Device->ModelName[0]));
235
236 return EFI_SUCCESS;
237 }
238
239 /**
240 Discover all partitions in the EMMC device.
241
242 @param[in] Device The pointer to the EMMC_DEVICE data structure.
243
244 @retval EFI_SUCCESS All the partitions in the device are successfully enumerated.
245 @return Others Some error occurs when enumerating the partitions.
246
247 **/
248 EFI_STATUS
249 DiscoverAllPartitions (
250 IN EMMC_DEVICE *Device
251 )
252 {
253 EFI_STATUS Status;
254 EMMC_PARTITION *Partition;
255 EMMC_CSD *Csd;
256 EMMC_CID *Cid;
257 EMMC_EXT_CSD *ExtCsd;
258 UINT8 Slot;
259 UINT64 Capacity;
260 UINT32 DevStatus;
261 UINT8 Index;
262 UINT32 SecCount;
263 UINT32 GpSizeMult;
264
265 Slot = Device->Slot;
266
267 Status = EmmcSendStatus (Device, Slot + 1, &DevStatus);
268 if (EFI_ERROR (Status)) {
269 return Status;
270 }
271 //
272 // Deselect the device to force it enter stby mode before getting CSD
273 // register content.
274 // Note here we don't judge return status as some EMMC devices return
275 // error but the state has been stby.
276 //
277 EmmcSelect (Device, 0);
278
279 Status = EmmcSendStatus (Device, Slot + 1, &DevStatus);
280 if (EFI_ERROR (Status)) {
281 return Status;
282 }
283
284 Csd = &Device->Csd;
285 Status = EmmcGetCsd (Device, Slot + 1, Csd);
286 if (EFI_ERROR (Status)) {
287 return Status;
288 }
289 DumpCsd (Csd);
290
291 if ((Csd->CSizeLow | Csd->CSizeHigh << 2) == 0xFFF) {
292 Device->SectorAddressing = TRUE;
293 } else {
294 Device->SectorAddressing = FALSE;
295 }
296
297 Cid = &Device->Cid;
298 Status = EmmcGetCid (Device, Slot + 1, Cid);
299 if (EFI_ERROR (Status)) {
300 return Status;
301 }
302
303 Status = EmmcSelect (Device, Slot + 1);
304 if (EFI_ERROR (Status)) {
305 return Status;
306 }
307
308 ExtCsd = &Device->ExtCsd;
309 Status = EmmcGetExtCsd (Device, ExtCsd);
310 if (EFI_ERROR (Status)) {
311 return Status;
312 }
313 DumpExtCsd (ExtCsd);
314
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;
318 }
319
320 if ((ExtCsd->PartitioningSupport & BIT0) != BIT0) {
321 DEBUG ((EFI_D_ERROR, "The EMMC device doesn't support Partition Feature!!!\n"));
322 return EFI_UNSUPPORTED;
323 }
324
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;
339
340 switch (Index) {
341 case EmmcPartitionUserData:
342 SecCount = *(UINT32*)&ExtCsd->SecCount;
343 Capacity = MultU64x32 ((UINT64) SecCount, 0x200);
344 break;
345 case EmmcPartitionBoot1:
346 case EmmcPartitionBoot2:
347 Capacity = ExtCsd->BootSizeMult * SIZE_128KB;
348 break;
349 case EmmcPartitionRPMB:
350 Capacity = ExtCsd->RpmbSizeMult * SIZE_128KB;
351 break;
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);
355 break;
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);
359 break;
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);
363 break;
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);
367 break;
368 default:
369 ASSERT (FALSE);
370 return EFI_INVALID_PARAMETER;
371 }
372
373 if (Capacity != 0) {
374 Partition->Enable = TRUE;
375 Partition->BlockMedia.LastBlock = DivU64x32 (Capacity, Partition->BlockMedia.BlockSize) - 1;
376 }
377
378 if ((ExtCsd->EraseGroupDef & BIT0) == 0) {
379 if (Csd->WriteBlLen < 9) {
380 Partition->EraseBlock.EraseLengthGranularity = 1;
381 } else {
382 Partition->EraseBlock.EraseLengthGranularity = (Csd->EraseGrpMult + 1) * (Csd->EraseGrpSize + 1) * (1 << (Csd->WriteBlLen - 9));
383 }
384 } else {
385 Partition->EraseBlock.EraseLengthGranularity = 1024 * ExtCsd->HcEraseGrpSize;
386 }
387 }
388
389 return EFI_SUCCESS;
390 }
391
392 /**
393 Install BlkIo, BlkIo2 and Ssp protocols for the specified partition in the EMMC device.
394
395 @param[in] Device The pointer to the EMMC_DEVICE data structure.
396 @param[in] Index The index of the partition.
397
398 @retval EFI_SUCCESS The protocols are installed successfully.
399 @retval Others Some error occurs when installing the protocols.
400
401 **/
402 EFI_STATUS
403 InstallProtocolOnPartition (
404 IN EMMC_DEVICE *Device,
405 IN UINT8 Index
406 )
407 {
408 EFI_STATUS Status;
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;
415
416 //
417 // Build device path
418 //
419 ParentDevicePath = Device->DevicePath;
420
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;
425
426 DevicePath = AppendDevicePathNode (ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&ControlNode);
427 if (DevicePath == NULL) {
428 Status = EFI_OUT_OF_RESOURCES;
429 goto Error;
430 }
431
432 DeviceHandle = NULL;
433 RemainingDevicePath = DevicePath;
434 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
435 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
436 Status = EFI_ALREADY_STARTED;
437 goto Error;
438 }
439
440 Partition = &Device->Partition[Index];
441 Partition->DevicePath = DevicePath;
442 if (Partition->Enable) {
443 //
444 // Install BlkIo/BlkIo2/Ssp for the specified partition
445 //
446 if (Partition->PartitionType != EmmcPartitionRPMB) {
447 Status = gBS->InstallMultipleProtocolInterfaces (
448 &Partition->Handle,
449 &gEfiDevicePathProtocolGuid,
450 Partition->DevicePath,
451 &gEfiBlockIoProtocolGuid,
452 &Partition->BlockIo,
453 &gEfiBlockIo2ProtocolGuid,
454 &Partition->BlockIo2,
455 &gEfiEraseBlockProtocolGuid,
456 &Partition->EraseBlock,
457 NULL
458 );
459 if (EFI_ERROR (Status)) {
460 goto Error;
461 }
462
463 if (((Partition->PartitionType == EmmcPartitionUserData) ||
464 (Partition->PartitionType == EmmcPartitionBoot1) ||
465 (Partition->PartitionType == EmmcPartitionBoot2)) &&
466 ((Device->Csd.Ccc & BIT10) != 0)) {
467 Status = gBS->InstallProtocolInterface (
468 &Partition->Handle,
469 &gEfiStorageSecurityCommandProtocolGuid,
470 EFI_NATIVE_INTERFACE,
471 &Partition->StorageSecurity
472 );
473 if (EFI_ERROR (Status)) {
474 gBS->UninstallMultipleProtocolInterfaces (
475 &Partition->Handle,
476 &gEfiDevicePathProtocolGuid,
477 Partition->DevicePath,
478 &gEfiBlockIoProtocolGuid,
479 &Partition->BlockIo,
480 &gEfiBlockIo2ProtocolGuid,
481 &Partition->BlockIo2,
482 &gEfiEraseBlockProtocolGuid,
483 &Partition->EraseBlock,
484 NULL
485 );
486 goto Error;
487 }
488 }
489
490 gBS->OpenProtocol (
491 Device->Private->Controller,
492 &gEfiSdMmcPassThruProtocolGuid,
493 (VOID **) &(Device->Private->PassThru),
494 Device->Private->DriverBindingHandle,
495 Partition->Handle,
496 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
497 );
498 }
499
500 } else {
501 Status = EFI_INVALID_PARAMETER;
502 }
503
504 Error:
505 if (EFI_ERROR (Status) && (DevicePath != NULL)) {
506 FreePool (DevicePath);
507 }
508
509 return Status;
510 }
511
512 /**
513 Scan EMMC Bus to discover the device.
514
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.
518
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
522 of resources.
523 @retval EFI_ALREADY_STARTED The device was discovered before.
524 @retval Others Fail to discover the device.
525
526 **/
527 EFI_STATUS
528 EFIAPI
529 DiscoverEmmcDevice (
530 IN EMMC_DRIVER_PRIVATE_DATA *Private,
531 IN UINT8 Slot,
532 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
533 )
534 {
535 EFI_STATUS Status;
536 EMMC_DEVICE *Device;
537 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
538 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
539 EFI_DEVICE_PATH_PROTOCOL *RemainingEmmcDevPath;
540 EFI_DEV_PATH *Node;
541 EFI_HANDLE DeviceHandle;
542 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
543 UINT8 Index;
544
545 Device = NULL;
546 DevicePath = NULL;
547 NewDevicePath = NULL;
548 RemainingDevicePath = NULL;
549 PassThru = Private->PassThru;
550 Device = &Private->Device[Slot];
551
552 //
553 // Build Device Path to check if the EMMC device present at the slot.
554 //
555 Status = PassThru->BuildDevicePath (
556 PassThru,
557 Slot,
558 &DevicePath
559 );
560 if (EFI_ERROR(Status)) {
561 return Status;
562 }
563
564 if (DevicePath->SubType != MSG_EMMC_DP) {
565 Status = EFI_UNSUPPORTED;
566 goto Error;
567 }
568
569 NewDevicePath = AppendDevicePathNode (
570 Private->ParentDevicePath,
571 DevicePath
572 );
573 if (NewDevicePath == NULL) {
574 Status = EFI_OUT_OF_RESOURCES;
575 goto Error;
576 }
577
578 DeviceHandle = NULL;
579 RemainingEmmcDevPath = NewDevicePath;
580 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingEmmcDevPath, &DeviceHandle);
581 //
582 // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized.
583 //
584 if (EFI_ERROR (Status) || (DeviceHandle == NULL) || !IsDevicePathEnd (RemainingEmmcDevPath)) {
585 Device->DevicePath = NewDevicePath;
586 Device->Slot = Slot;
587 Device->Private = Private;
588 //
589 // Expose user area in the Sd memory card to upper layer.
590 //
591 Status = DiscoverAllPartitions (Device);
592 if (EFI_ERROR(Status)) {
593 FreePool (NewDevicePath);
594 goto Error;
595 }
596
597 Status = gBS->InstallProtocolInterface (
598 &Device->Handle,
599 &gEfiDevicePathProtocolGuid,
600 EFI_NATIVE_INTERFACE,
601 Device->DevicePath
602 );
603 if (EFI_ERROR(Status)) {
604 FreePool (NewDevicePath);
605 goto Error;
606 }
607
608 Device->ControllerNameTable = NULL;
609 GetEmmcModelName (Device, &Device->Cid);
610 AddUnicodeString2 (
611 "eng",
612 gEmmcDxeComponentName.SupportedLanguages,
613 &Device->ControllerNameTable,
614 Device->ModelName,
615 TRUE
616 );
617 AddUnicodeString2 (
618 "en",
619 gEmmcDxeComponentName.SupportedLanguages,
620 &Device->ControllerNameTable,
621 Device->ModelName,
622 FALSE
623 );
624 }
625
626 if (RemainingDevicePath == NULL) {
627 //
628 // Expose all partitions in the Emmc device to upper layer.
629 //
630 for (Index = 0; Index < EMMC_MAX_PARTITIONS; Index++) {
631 InstallProtocolOnPartition (Device, Index);
632 }
633 } else if (!IsDevicePathEnd (RemainingDevicePath)) {
634 //
635 // Enumerate the specified partition
636 //
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;
642 goto Error;
643 }
644
645 Index = (UINT8)Node->Controller.ControllerNumber;
646 if (Index >= EMMC_MAX_PARTITIONS) {
647 Status = EFI_INVALID_PARAMETER;
648 goto Error;
649 }
650
651 Status = InstallProtocolOnPartition (Device, Index);
652 }
653
654 Error:
655 FreePool (DevicePath);
656
657 return Status;
658 }
659
660 /**
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.
663
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.
677
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
688 bus driver.
689
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
694 specified by This.
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.
701 **/
702 EFI_STATUS
703 EFIAPI
704 EmmcDxeDriverBindingSupported (
705 IN EFI_DRIVER_BINDING_PROTOCOL *This,
706 IN EFI_HANDLE Controller,
707 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
708 )
709 {
710 EFI_STATUS Status;
711 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
712 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
713 UINT8 Slot;
714
715 //
716 // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
717 //
718 Status = gBS->OpenProtocol (
719 Controller,
720 &gEfiSdMmcPassThruProtocolGuid,
721 (VOID**) &PassThru,
722 This->DriverBindingHandle,
723 Controller,
724 EFI_OPEN_PROTOCOL_BY_DRIVER
725 );
726
727 if (Status == EFI_ALREADY_STARTED) {
728 return EFI_SUCCESS;
729 }
730
731 if (EFI_ERROR (Status)) {
732 return Status;
733 }
734
735 //
736 // Test RemainingDevicePath is valid or not.
737 //
738 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
739 Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
740 if (EFI_ERROR (Status)) {
741 //
742 // Close the I/O Abstraction(s) used to perform the supported test
743 //
744 gBS->CloseProtocol (
745 Controller,
746 &gEfiSdMmcPassThruProtocolGuid,
747 This->DriverBindingHandle,
748 Controller
749 );
750 return Status;
751 }
752 }
753
754 //
755 // Close the I/O Abstraction(s) used to perform the supported test
756 //
757 gBS->CloseProtocol (
758 Controller,
759 &gEfiSdMmcPassThruProtocolGuid,
760 This->DriverBindingHandle,
761 Controller
762 );
763
764 //
765 // Open the EFI Device Path protocol needed to perform the supported test
766 //
767 Status = gBS->OpenProtocol (
768 Controller,
769 &gEfiDevicePathProtocolGuid,
770 (VOID **) &ParentDevicePath,
771 This->DriverBindingHandle,
772 Controller,
773 EFI_OPEN_PROTOCOL_GET_PROTOCOL
774 );
775 return Status;
776 }
777
778 /**
779 Starts a device controller or a bus controller.
780
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.
790
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
805 driver.
806
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.
811
812 **/
813 EFI_STATUS
814 EFIAPI
815 EmmcDxeDriverBindingStart (
816 IN EFI_DRIVER_BINDING_PROTOCOL *This,
817 IN EFI_HANDLE Controller,
818 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
819 )
820 {
821 EFI_STATUS Status;
822 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
823 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
824 EMMC_DRIVER_PRIVATE_DATA *Private;
825 UINT8 Slot;
826
827 Private = NULL;
828 PassThru = NULL;
829 Status = gBS->OpenProtocol (
830 Controller,
831 &gEfiSdMmcPassThruProtocolGuid,
832 (VOID **) &PassThru,
833 This->DriverBindingHandle,
834 Controller,
835 EFI_OPEN_PROTOCOL_BY_DRIVER
836 );
837 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
838 return Status;
839 }
840
841 //
842 // Check EFI_ALREADY_STARTED to reuse the original EMMC_DRIVER_PRIVATE_DATA.
843 //
844 if (Status != EFI_ALREADY_STARTED) {
845 Private = AllocateZeroPool (sizeof (EMMC_DRIVER_PRIVATE_DATA));
846 if (Private == NULL) {
847 Status = EFI_OUT_OF_RESOURCES;
848 goto Error;
849 }
850
851 Status = gBS->OpenProtocol (
852 Controller,
853 &gEfiDevicePathProtocolGuid,
854 (VOID **) &ParentDevicePath,
855 This->DriverBindingHandle,
856 Controller,
857 EFI_OPEN_PROTOCOL_GET_PROTOCOL
858 );
859 ASSERT_EFI_ERROR (Status);
860 Private->PassThru = PassThru;
861 Private->Controller = Controller;
862 Private->ParentDevicePath = ParentDevicePath;
863 Private->DriverBindingHandle = This->DriverBindingHandle;
864
865 Status = gBS->InstallProtocolInterface (
866 &Controller,
867 &gEfiCallerIdGuid,
868 EFI_NATIVE_INTERFACE,
869 Private
870 );
871 if (EFI_ERROR (Status)) {
872 goto Error;
873 }
874 } else {
875 Status = gBS->OpenProtocol (
876 Controller,
877 &gEfiCallerIdGuid,
878 (VOID **) &Private,
879 This->DriverBindingHandle,
880 Controller,
881 EFI_OPEN_PROTOCOL_GET_PROTOCOL
882 );
883 if (EFI_ERROR (Status)) {
884 goto Error;
885 }
886 }
887
888 if (RemainingDevicePath == NULL) {
889 Slot = 0xFF;
890 while (TRUE) {
891 Status = PassThru->GetNextSlot (PassThru, &Slot);
892 if (EFI_ERROR (Status)) {
893 //
894 // Cannot find more legal slots.
895 //
896 Status = EFI_SUCCESS;
897 break;
898 }
899
900 Status = DiscoverEmmcDevice (Private, Slot, NULL);
901 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
902 break;
903 }
904 }
905 } else if (!IsDevicePathEnd (RemainingDevicePath)) {
906 Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
907 if (!EFI_ERROR (Status)) {
908 Status = DiscoverEmmcDevice (Private, Slot, NextDevicePathNode (RemainingDevicePath));
909 }
910 }
911
912 Error:
913 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
914 gBS->CloseProtocol (
915 Controller,
916 &gEfiSdMmcPassThruProtocolGuid,
917 This->DriverBindingHandle,
918 Controller
919 );
920
921 if (Private != NULL) {
922 gBS->UninstallMultipleProtocolInterfaces (
923 Controller,
924 &gEfiCallerIdGuid,
925 Private,
926 NULL
927 );
928 FreePool (Private);
929 }
930 }
931 return Status;
932 }
933
934 /**
935 Stops a device controller or a bus controller.
936
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.
947
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.
955
956 @retval EFI_SUCCESS The device was stopped.
957 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
958
959 **/
960 EFI_STATUS
961 EFIAPI
962 EmmcDxeDriverBindingStop (
963 IN EFI_DRIVER_BINDING_PROTOCOL *This,
964 IN EFI_HANDLE Controller,
965 IN UINTN NumberOfChildren,
966 IN EFI_HANDLE *ChildHandleBuffer
967 )
968 {
969 EFI_STATUS Status;
970 BOOLEAN AllChildrenStopped;
971 UINTN Index;
972 EFI_DEVICE_PATH_PROTOCOL *DevicePath;
973 EMMC_DRIVER_PRIVATE_DATA *Private;
974 EMMC_DEVICE *Device;
975 EMMC_PARTITION *Partition;
976 EFI_BLOCK_IO_PROTOCOL *BlockIo;
977 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
978 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;
979 LIST_ENTRY *Link;
980 LIST_ENTRY *NextLink;
981 EMMC_REQUEST *Request;
982
983 BlockIo = NULL;
984 BlockIo2 = NULL;
985 if (NumberOfChildren == 0) {
986 Status = gBS->OpenProtocol (
987 Controller,
988 &gEfiCallerIdGuid,
989 (VOID **) &Private,
990 This->DriverBindingHandle,
991 Controller,
992 EFI_OPEN_PROTOCOL_GET_PROTOCOL
993 );
994 if (EFI_ERROR (Status)) {
995 return EFI_DEVICE_ERROR;
996 }
997
998 for (Index = 0; Index < EMMC_MAX_DEVICES; Index++) {
999 Device = &Private->Device[Index];
1000 Status = gBS->OpenProtocol (
1001 Device->Handle,
1002 &gEfiDevicePathProtocolGuid,
1003 (VOID **) &DevicePath,
1004 This->DriverBindingHandle,
1005 Controller,
1006 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1007 );
1008 if (EFI_ERROR (Status)) {
1009 continue;
1010 }
1011 ASSERT (DevicePath == Device->DevicePath);
1012 gBS->UninstallProtocolInterface (
1013 Device->Handle,
1014 &gEfiDevicePathProtocolGuid,
1015 DevicePath
1016 );
1017 FreePool (Device->DevicePath);
1018 }
1019
1020 gBS->UninstallProtocolInterface (
1021 Controller,
1022 &gEfiCallerIdGuid,
1023 Private
1024 );
1025 gBS->CloseProtocol (
1026 Controller,
1027 &gEfiSdMmcPassThruProtocolGuid,
1028 This->DriverBindingHandle,
1029 Controller
1030 );
1031 FreePool (Private);
1032
1033 return EFI_SUCCESS;
1034 }
1035
1036 AllChildrenStopped = TRUE;
1037
1038 for (Index = 0; Index < NumberOfChildren; Index++) {
1039 Status = gBS->OpenProtocol (
1040 ChildHandleBuffer[Index],
1041 &gEfiBlockIoProtocolGuid,
1042 (VOID **) &BlockIo,
1043 This->DriverBindingHandle,
1044 Controller,
1045 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1046 );
1047 if (EFI_ERROR (Status)) {
1048 Status = gBS->OpenProtocol (
1049 ChildHandleBuffer[Index],
1050 &gEfiBlockIo2ProtocolGuid,
1051 (VOID **) &BlockIo2,
1052 This->DriverBindingHandle,
1053 Controller,
1054 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1055 );
1056 if (EFI_ERROR (Status)) {
1057 AllChildrenStopped = FALSE;
1058 continue;
1059 }
1060 }
1061
1062 if (BlockIo != NULL) {
1063 Partition = EMMC_PARTITION_DATA_FROM_BLKIO (BlockIo);
1064 } else {
1065 ASSERT (BlockIo2 != NULL);
1066 Partition = EMMC_PARTITION_DATA_FROM_BLKIO2 (BlockIo2);
1067 }
1068
1069 for (Link = GetFirstNode (&Partition->Queue);
1070 !IsNull (&Partition->Queue, Link);
1071 Link = NextLink) {
1072 NextLink = GetNextNode (&Partition->Queue, Link);
1073
1074 RemoveEntryList (Link);
1075 Request = EMMC_REQUEST_FROM_LINK (Link);
1076
1077 gBS->CloseEvent (Request->Event);
1078 Request->Token->TransactionStatus = EFI_ABORTED;
1079
1080 if (Request->IsEnd) {
1081 gBS->SignalEvent (Request->Token->Event);
1082 }
1083
1084 FreePool (Request);
1085 }
1086
1087 //
1088 // Close the child handle
1089 //
1090 Status = gBS->CloseProtocol (
1091 Controller,
1092 &gEfiSdMmcPassThruProtocolGuid,
1093 This->DriverBindingHandle,
1094 ChildHandleBuffer[Index]
1095 );
1096
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,
1107 NULL
1108 );
1109 if (EFI_ERROR (Status)) {
1110 AllChildrenStopped = FALSE;
1111 gBS->OpenProtocol (
1112 Controller,
1113 &gEfiSdMmcPassThruProtocolGuid,
1114 (VOID **)&Partition->Device->Private->PassThru,
1115 This->DriverBindingHandle,
1116 ChildHandleBuffer[Index],
1117 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1118 );
1119 continue;
1120 }
1121
1122 //
1123 // If Storage Security Command Protocol is installed, then uninstall this protocol.
1124 //
1125 Status = gBS->OpenProtocol (
1126 ChildHandleBuffer[Index],
1127 &gEfiStorageSecurityCommandProtocolGuid,
1128 (VOID **) &StorageSecurity,
1129 This->DriverBindingHandle,
1130 Controller,
1131 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1132 );
1133
1134 if (!EFI_ERROR (Status)) {
1135 Status = gBS->UninstallProtocolInterface (
1136 ChildHandleBuffer[Index],
1137 &gEfiStorageSecurityCommandProtocolGuid,
1138 &Partition->StorageSecurity
1139 );
1140 if (EFI_ERROR (Status)) {
1141 gBS->OpenProtocol (
1142 Controller,
1143 &gEfiSdMmcPassThruProtocolGuid,
1144 (VOID **) &Partition->Device->Private->PassThru,
1145 This->DriverBindingHandle,
1146 ChildHandleBuffer[Index],
1147 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1148 );
1149 AllChildrenStopped = FALSE;
1150 continue;
1151 }
1152 }
1153
1154 FreePool (Partition->DevicePath);
1155 }
1156
1157 if (!AllChildrenStopped) {
1158 return EFI_DEVICE_ERROR;
1159 }
1160
1161 return EFI_SUCCESS;
1162 }
1163
1164 /**
1165 The user Entry Point for module EmmcDxe. The user code starts with this function.
1166
1167 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1168 @param[in] SystemTable A pointer to the EFI System Table.
1169
1170 @retval EFI_SUCCESS The entry point is executed successfully.
1171 @retval other Some errors occur when executing this entry point.
1172
1173 **/
1174 EFI_STATUS
1175 EFIAPI
1176 InitializeEmmcDxe (
1177 IN EFI_HANDLE ImageHandle,
1178 IN EFI_SYSTEM_TABLE *SystemTable
1179 )
1180 {
1181 EFI_STATUS Status;
1182
1183 //
1184 // Install driver model protocol(s).
1185 //
1186 Status = EfiLibInstallDriverBindingComponentName2 (
1187 ImageHandle,
1188 SystemTable,
1189 &gEmmcDxeDriverBinding,
1190 ImageHandle,
1191 &gEmmcDxeComponentName,
1192 &gEmmcDxeComponentName2
1193 );
1194 ASSERT_EFI_ERROR (Status);
1195
1196 return Status;
1197 }
1198