]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
SecurityPkg: Tcg2Dxe: Fix undersized TempBuf
[mirror_edk2.git] / MdeModulePkg / Bus / Sd / EmmcDxe / EmmcDxe.c
CommitLineData
48555339
FT
1/** @file\r
2 The EmmcDxe driver is used to manage the EMMC device.\r
3\r
4 It produces BlockIo, BlockIo2 and StorageSecurity protocols to allow upper layer\r
5 access the EMMC device.\r
6\r
7 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
8 This program and the accompanying materials\r
9 are licensed and made available under the terms and conditions of the BSD License\r
10 which accompanies this distribution. The full text of the license may be found at\r
11 http://opensource.org/licenses/bsd-license.php\r
12\r
13 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
14 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
15\r
16**/\r
17\r
18#include "EmmcDxe.h"\r
19\r
20//\r
21// EmmcDxe Driver Binding Protocol Instance\r
22//\r
23EFI_DRIVER_BINDING_PROTOCOL gEmmcDxeDriverBinding = {\r
24 EmmcDxeDriverBindingSupported,\r
25 EmmcDxeDriverBindingStart,\r
26 EmmcDxeDriverBindingStop,\r
27 0x10,\r
28 NULL,\r
29 NULL\r
30};\r
31\r
32//\r
33// Template for Emmc Partitions.\r
34//\r
35EMMC_PARTITION mEmmcPartitionTemplate = {\r
36 EMMC_PARTITION_SIGNATURE, // Signature\r
37 FALSE, // Enable\r
38 EmmcPartitionUnknown, // PartitionType\r
39 NULL, // Handle\r
40 NULL, // DevicePath\r
41 { // BlockIo\r
42 EFI_BLOCK_IO_PROTOCOL_REVISION,\r
43 NULL,\r
44 EmmcReset,\r
45 EmmcReadBlocks,\r
46 EmmcWriteBlocks,\r
47 EmmcFlushBlocks\r
48 },\r
49 { // BlockIo2\r
50 NULL,\r
51 EmmcResetEx,\r
52 EmmcReadBlocksEx,\r
53 EmmcWriteBlocksEx,\r
54 EmmcFlushBlocksEx\r
55 },\r
56 { // BlockMedia\r
57 0, // MediaId\r
58 FALSE, // RemovableMedia\r
59 TRUE, // MediaPresent\r
60 FALSE, // LogicPartition\r
61 FALSE, // ReadOnly\r
62 FALSE, // WritingCache\r
63 0x200, // BlockSize\r
64 0, // IoAlign\r
65 0 // LastBlock\r
66 },\r
67 { // StorageSecurity\r
68 EmmcSecurityProtocolIn,\r
69 EmmcSecurityProtocolOut\r
70 },\r
71 {\r
72 NULL,\r
73 NULL\r
74 },\r
75 NULL // Device\r
76};\r
77\r
78/**\r
79 Decode and print EMMC CSD Register content.\r
80\r
81 @param[in] Csd Pointer to EMMC_CSD data structure.\r
82\r
83 @retval EFI_SUCCESS The function completed successfully\r
84**/\r
85EFI_STATUS\r
86DumpCsd (\r
87 IN EMMC_CSD *Csd\r
88 )\r
89{\r
90 DEBUG((DEBUG_INFO, "== Dump Emmc Csd Register==\n"));\r
91 DEBUG((DEBUG_INFO, " CSD structure 0x%x\n", Csd->CsdStructure));\r
92 DEBUG((DEBUG_INFO, " System specification version 0x%x\n", Csd->SpecVers));\r
93 DEBUG((DEBUG_INFO, " Data read access-time 1 0x%x\n", Csd->Taac));\r
94 DEBUG((DEBUG_INFO, " Data read access-time 2 0x%x\n", Csd->Nsac));\r
95 DEBUG((DEBUG_INFO, " Max. bus clock frequency 0x%x\n", Csd->TranSpeed));\r
96 DEBUG((DEBUG_INFO, " Device command classes 0x%x\n", Csd->Ccc));\r
97 DEBUG((DEBUG_INFO, " Max. read data block length 0x%x\n", Csd->ReadBlLen));\r
98 DEBUG((DEBUG_INFO, " Partial blocks for read allowed 0x%x\n", Csd->ReadBlPartial));\r
99 DEBUG((DEBUG_INFO, " Write block misalignment 0x%x\n", Csd->WriteBlkMisalign));\r
100 DEBUG((DEBUG_INFO, " Read block misalignment 0x%x\n", Csd->ReadBlkMisalign));\r
101 DEBUG((DEBUG_INFO, " DSR implemented 0x%x\n", Csd->DsrImp));\r
102 DEBUG((DEBUG_INFO, " Device size 0x%x\n", Csd->CSizeLow | (Csd->CSizeHigh << 2)));\r
103 DEBUG((DEBUG_INFO, " Max. read current @ VDD min 0x%x\n", Csd->VddRCurrMin));\r
104 DEBUG((DEBUG_INFO, " Max. read current @ VDD max 0x%x\n", Csd->VddRCurrMax));\r
105 DEBUG((DEBUG_INFO, " Max. write current @ VDD min 0x%x\n", Csd->VddWCurrMin));\r
106 DEBUG((DEBUG_INFO, " Max. write current @ VDD max 0x%x\n", Csd->VddWCurrMax));\r
107 DEBUG((DEBUG_INFO, " Device size multiplier 0x%x\n", Csd->CSizeMult));\r
108 DEBUG((DEBUG_INFO, " Erase group size 0x%x\n", Csd->EraseGrpSize));\r
109 DEBUG((DEBUG_INFO, " Erase group size multiplier 0x%x\n", Csd->EraseGrpMult));\r
110 DEBUG((DEBUG_INFO, " Write protect group size 0x%x\n", Csd->WpGrpSize));\r
111 DEBUG((DEBUG_INFO, " Write protect group enable 0x%x\n", Csd->WpGrpEnable));\r
112 DEBUG((DEBUG_INFO, " Manufacturer default ECC 0x%x\n", Csd->DefaultEcc));\r
113 DEBUG((DEBUG_INFO, " Write speed factor 0x%x\n", Csd->R2WFactor));\r
114 DEBUG((DEBUG_INFO, " Max. write data block length 0x%x\n", Csd->WriteBlLen));\r
115 DEBUG((DEBUG_INFO, " Partial blocks for write allowed 0x%x\n", Csd->WriteBlPartial));\r
116 DEBUG((DEBUG_INFO, " Content protection application 0x%x\n", Csd->ContentProtApp));\r
117 DEBUG((DEBUG_INFO, " File format group 0x%x\n", Csd->FileFormatGrp));\r
118 DEBUG((DEBUG_INFO, " Copy flag (OTP) 0x%x\n", Csd->Copy));\r
119 DEBUG((DEBUG_INFO, " Permanent write protection 0x%x\n", Csd->PermWriteProtect));\r
120 DEBUG((DEBUG_INFO, " Temporary write protection 0x%x\n", Csd->TmpWriteProtect));\r
121 DEBUG((DEBUG_INFO, " File format 0x%x\n", Csd->FileFormat));\r
122 DEBUG((DEBUG_INFO, " ECC code 0x%x\n", Csd->Ecc));\r
123\r
124 return EFI_SUCCESS;\r
125}\r
126\r
127/**\r
128 Decode and print EMMC EXT_CSD Register content.\r
129\r
130 @param[in] ExtCsd Pointer to the EMMC_EXT_CSD data structure.\r
131\r
132 @retval EFI_SUCCESS The function completed successfully\r
133**/\r
134EFI_STATUS\r
135DumpExtCsd (\r
136 IN EMMC_EXT_CSD *ExtCsd\r
137 )\r
138{\r
139 DEBUG((DEBUG_INFO, "==Dump Emmc ExtCsd Register==\n"));\r
140 DEBUG((DEBUG_INFO, " Supported Command Sets 0x%x\n", ExtCsd->CmdSet));\r
141 DEBUG((DEBUG_INFO, " HPI features 0x%x\n", ExtCsd->HpiFeatures));\r
142 DEBUG((DEBUG_INFO, " Background operations support 0x%x\n", ExtCsd->BkOpsSupport));\r
143 DEBUG((DEBUG_INFO, " Background operations status 0x%x\n", ExtCsd->BkopsStatus));\r
144 DEBUG((DEBUG_INFO, " Number of correctly programmed sectors 0x%x\n", *((UINT32*)&ExtCsd->CorrectlyPrgSectorsNum[0])));\r
145 DEBUG((DEBUG_INFO, " Initialization time after partitioning 0x%x\n", ExtCsd->IniTimeoutAp));\r
146 DEBUG((DEBUG_INFO, " TRIM Multiplier 0x%x\n", ExtCsd->TrimMult));\r
147 DEBUG((DEBUG_INFO, " Secure Feature support 0x%x\n", ExtCsd->SecFeatureSupport));\r
148 DEBUG((DEBUG_INFO, " Secure Erase Multiplier 0x%x\n", ExtCsd->SecEraseMult));\r
149 DEBUG((DEBUG_INFO, " Secure TRIM Multiplier 0x%x\n", ExtCsd->SecTrimMult));\r
150 DEBUG((DEBUG_INFO, " Boot information 0x%x\n", ExtCsd->BootInfo));\r
151 DEBUG((DEBUG_INFO, " Boot partition size 0x%x\n", ExtCsd->BootSizeMult));\r
152 DEBUG((DEBUG_INFO, " Access size 0x%x\n", ExtCsd->AccSize));\r
153 DEBUG((DEBUG_INFO, " High-capacity erase unit size 0x%x\n", ExtCsd->HcEraseGrpSize));\r
154 DEBUG((DEBUG_INFO, " High-capacity erase timeout 0x%x\n", ExtCsd->EraseTimeoutMult));\r
155 DEBUG((DEBUG_INFO, " Reliable write sector count 0x%x\n", ExtCsd->RelWrSecC));\r
156 DEBUG((DEBUG_INFO, " High-capacity write protect group size 0x%x\n", ExtCsd->HcWpGrpSize));\r
157 DEBUG((DEBUG_INFO, " Sleep/awake timeout 0x%x\n", ExtCsd->SATimeout));\r
158 DEBUG((DEBUG_INFO, " Sector Count 0x%x\n", *((UINT32*)&ExtCsd->SecCount[0])));\r
159 DEBUG((DEBUG_INFO, " Partition switching timing 0x%x\n", ExtCsd->PartitionSwitchTime));\r
160 DEBUG((DEBUG_INFO, " Out-of-interrupt busy timing 0x%x\n", ExtCsd->OutOfInterruptTime));\r
161 DEBUG((DEBUG_INFO, " I/O Driver Strength 0x%x\n", ExtCsd->DriverStrength));\r
162 DEBUG((DEBUG_INFO, " Device type 0x%x\n", ExtCsd->DeviceType));\r
163 DEBUG((DEBUG_INFO, " CSD STRUCTURE 0x%x\n", ExtCsd->CsdStructure));\r
164 DEBUG((DEBUG_INFO, " Extended CSD revision 0x%x\n", ExtCsd->ExtCsdRev));\r
165 DEBUG((DEBUG_INFO, " Command set 0x%x\n", ExtCsd->CmdSet));\r
166 DEBUG((DEBUG_INFO, " Command set revision 0x%x\n", ExtCsd->CmdSetRev));\r
167 DEBUG((DEBUG_INFO, " Power class 0x%x\n", ExtCsd->PowerClass));\r
168 DEBUG((DEBUG_INFO, " High-speed interface timing 0x%x\n", ExtCsd->HsTiming));\r
169 DEBUG((DEBUG_INFO, " Bus width mode 0x%x\n", ExtCsd->BusWidth));\r
170 DEBUG((DEBUG_INFO, " Erased memory content 0x%x\n", ExtCsd->ErasedMemCont));\r
171 DEBUG((DEBUG_INFO, " Partition configuration 0x%x\n", ExtCsd->PartitionConfig));\r
172 DEBUG((DEBUG_INFO, " Boot config protection 0x%x\n", ExtCsd->BootConfigProt));\r
173 DEBUG((DEBUG_INFO, " Boot bus Conditions 0x%x\n", ExtCsd->BootBusConditions));\r
174 DEBUG((DEBUG_INFO, " High-density erase group definition 0x%x\n", ExtCsd->EraseGroupDef));\r
175 DEBUG((DEBUG_INFO, " Boot write protection status register 0x%x\n", ExtCsd->BootWpStatus));\r
176 DEBUG((DEBUG_INFO, " Boot area write protection register 0x%x\n", ExtCsd->BootWp));\r
177 DEBUG((DEBUG_INFO, " User area write protection register 0x%x\n", ExtCsd->UserWp));\r
178 DEBUG((DEBUG_INFO, " FW configuration 0x%x\n", ExtCsd->FwConfig));\r
179 DEBUG((DEBUG_INFO, " RPMB Size 0x%x\n", ExtCsd->RpmbSizeMult));\r
180 DEBUG((DEBUG_INFO, " H/W reset function 0x%x\n", ExtCsd->RstFunction));\r
181 DEBUG((DEBUG_INFO, " Partitioning Support 0x%x\n", ExtCsd->PartitioningSupport));\r
182 DEBUG((DEBUG_INFO, " Max Enhanced Area Size 0x%02x%02x%02x\n", \\r
183 ExtCsd->MaxEnhSizeMult[2], ExtCsd->MaxEnhSizeMult[1], ExtCsd->MaxEnhSizeMult[0]));\r
184 DEBUG((DEBUG_INFO, " Partitions attribute 0x%x\n", ExtCsd->PartitionsAttribute));\r
185 DEBUG((DEBUG_INFO, " Partitioning Setting 0x%x\n", ExtCsd->PartitionSettingCompleted));\r
186 DEBUG((DEBUG_INFO, " General Purpose Partition 1 Size 0x%02x%02x%02x\n", \\r
187 ExtCsd->GpSizeMult[2], ExtCsd->GpSizeMult[1], ExtCsd->GpSizeMult[0]));\r
188 DEBUG((DEBUG_INFO, " General Purpose Partition 2 Size 0x%02x%02x%02x\n", \\r
189 ExtCsd->GpSizeMult[5], ExtCsd->GpSizeMult[4], ExtCsd->GpSizeMult[3]));\r
190 DEBUG((DEBUG_INFO, " General Purpose Partition 3 Size 0x%02x%02x%02x\n", \\r
191 ExtCsd->GpSizeMult[8], ExtCsd->GpSizeMult[7], ExtCsd->GpSizeMult[6]));\r
192 DEBUG((DEBUG_INFO, " General Purpose Partition 4 Size 0x%02x%02x%02x\n", \\r
193 ExtCsd->GpSizeMult[11], ExtCsd->GpSizeMult[10], ExtCsd->GpSizeMult[9]));\r
194 DEBUG((DEBUG_INFO, " Enhanced User Data Area Size 0x%02x%02x%02x\n", \\r
195 ExtCsd->EnhSizeMult[2], ExtCsd->EnhSizeMult[1], ExtCsd->EnhSizeMult[0]));\r
196 DEBUG((DEBUG_INFO, " Enhanced User Data Start Address 0x%x\n", *((UINT32*)&ExtCsd->EnhStartAddr[0])));\r
197 DEBUG((DEBUG_INFO, " Bad Block Management mode 0x%x\n", ExtCsd->SecBadBlkMgmnt));\r
198 DEBUG((DEBUG_INFO, " Native sector size 0x%x\n", ExtCsd->NativeSectorSize));\r
199 DEBUG((DEBUG_INFO, " Sector size emulation 0x%x\n", ExtCsd->UseNativeSector));\r
200 DEBUG((DEBUG_INFO, " Sector size 0x%x\n", ExtCsd->DataSectorSize));\r
201\r
202 return EFI_SUCCESS;\r
203}\r
204\r
205/**\r
206 Get EMMC device model name.\r
207\r
208 @param[in, out] Device The pointer to the EMMC_DEVICE data structure.\r
209 @param[in] Cid Pointer to EMMC_CID data structure.\r
210\r
211 @retval EFI_SUCCESS The function completed successfully\r
212\r
213**/\r
214EFI_STATUS\r
215GetEmmcModelName (\r
216 IN OUT EMMC_DEVICE *Device,\r
217 IN EMMC_CID *Cid\r
218 )\r
219{\r
220 CHAR8 String[EMMC_MODEL_NAME_MAX_LEN];\r
221\r
222 ZeroMem (String, sizeof (String));\r
223 CopyMem (String, &Cid->OemId, sizeof (Cid->OemId));\r
224 String[sizeof (Cid->OemId)] = ' ';\r
225 CopyMem (String + sizeof (Cid->OemId) + 1, Cid->ProductName, sizeof (Cid->ProductName));\r
226 String[sizeof (Cid->OemId) + sizeof (Cid->ProductName)] = ' ';\r
227 CopyMem (String + sizeof (Cid->OemId) + sizeof (Cid->ProductName) + 1, Cid->ProductSerialNumber, sizeof (Cid->ProductSerialNumber));\r
228\r
229 AsciiStrToUnicodeStr (String, Device->ModelName);\r
230\r
231 return EFI_SUCCESS;\r
232}\r
233\r
234/**\r
235 Discover all partitions in the EMMC device.\r
236\r
237 @param[in] Device The pointer to the EMMC_DEVICE data structure.\r
238\r
239 @retval EFI_SUCCESS All the partitions in the device are successfully enumerated.\r
240 @return Others Some error occurs when enumerating the partitions.\r
241\r
242**/\r
243EFI_STATUS\r
244DiscoverAllPartitions (\r
245 IN EMMC_DEVICE *Device\r
246 )\r
247{\r
248 EFI_STATUS Status;\r
249 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
250 EMMC_PARTITION *Partition;\r
251 EMMC_CSD *Csd;\r
252 EMMC_CID *Cid;\r
253 EMMC_EXT_CSD *ExtCsd;\r
254 UINT8 Slot;\r
255 UINT64 Capacity;\r
256 UINT32 DevStatus;\r
257 UINT8 Index;\r
258 UINT32 SecCount;\r
259 UINT32 GpSizeMult;\r
260\r
261 PassThru = Device->Private->PassThru;\r
262 Slot = Device->Slot;\r
263\r
264 Status = EmmcSendStatus (Device, Slot + 1, &DevStatus);\r
265 if (EFI_ERROR (Status)) {\r
266 return Status;\r
267 }\r
268 //\r
269 // Deselect the device to force it enter stby mode before getting CSD\r
270 // register content.\r
271 // Note here we don't judge return status as some EMMC devices return\r
272 // error but the state has been stby.\r
273 //\r
274 EmmcSelect (Device, 0);\r
275\r
276 Status = EmmcSendStatus (Device, Slot + 1, &DevStatus);\r
277 if (EFI_ERROR (Status)) {\r
278 return Status;\r
279 }\r
280\r
281 Csd = &Device->Csd;\r
282 Status = EmmcGetCsd (Device, Slot + 1, Csd);\r
283 if (EFI_ERROR (Status)) {\r
284 return Status;\r
285 }\r
286 DumpCsd (Csd);\r
287\r
288 if ((Csd->CSizeLow | Csd->CSizeHigh << 2) == 0xFFF) {\r
289 Device->SectorAddressing = TRUE;\r
290 } else {\r
291 Device->SectorAddressing = FALSE;\r
292 }\r
293\r
294 Cid = &Device->Cid;\r
295 Status = EmmcGetCid (Device, Slot + 1, Cid);\r
296 if (EFI_ERROR (Status)) {\r
297 return Status;\r
298 }\r
299\r
300 Status = EmmcSelect (Device, Slot + 1);\r
301 if (EFI_ERROR (Status)) {\r
302 return Status;\r
303 }\r
304\r
305 ExtCsd = &Device->ExtCsd;\r
306 Status = EmmcGetExtCsd (Device, ExtCsd);\r
307 if (EFI_ERROR (Status)) {\r
308 return Status;\r
309 }\r
310 DumpExtCsd (ExtCsd);\r
311\r
312 if (ExtCsd->ExtCsdRev < 5) {\r
313 DEBUG ((EFI_D_ERROR, "The EMMC device version is too low, we don't support!!!\n"));\r
314 return EFI_UNSUPPORTED;\r
315 }\r
316\r
317 if ((ExtCsd->PartitioningSupport & BIT0) != BIT0) {\r
318 DEBUG ((EFI_D_ERROR, "The EMMC device doesn't support Partition Feature!!!\n"));\r
319 return EFI_UNSUPPORTED;\r
320 }\r
321\r
322 for (Index = 0; Index < EMMC_MAX_PARTITIONS; Index++) {\r
323 Partition = &Device->Partition[Index];\r
324 CopyMem (Partition, &mEmmcPartitionTemplate, sizeof (EMMC_PARTITION));\r
325 Partition->Device = Device;\r
326 InitializeListHead (&Partition->Queue);\r
327 Partition->BlockIo.Media = &Partition->BlockMedia;\r
328 Partition->BlockIo2.Media = &Partition->BlockMedia;\r
329 Partition->PartitionType = Index;\r
330 Partition->BlockMedia.IoAlign = Device->Private->PassThru->IoAlign;\r
331 Partition->BlockMedia.BlockSize = 0x200;\r
332 Partition->BlockMedia.LastBlock = 0x00;\r
333 Partition->BlockMedia.RemovableMedia = FALSE;\r
334 Partition->BlockMedia.MediaPresent = TRUE;\r
335 Partition->BlockMedia.LogicalPartition = FALSE;\r
336\r
337 switch (Index) {\r
338 case EmmcPartitionUserData:\r
339 SecCount = *(UINT32*)&ExtCsd->SecCount;\r
340 Capacity = MultU64x32 ((UINT64) SecCount, 0x200);\r
341 break;\r
342 case EmmcPartitionBoot1:\r
343 case EmmcPartitionBoot2:\r
344 Capacity = ExtCsd->BootSizeMult * SIZE_128KB;\r
345 break;\r
346 case EmmcPartitionRPMB:\r
347 Capacity = ExtCsd->RpmbSizeMult * SIZE_128KB;\r
348 break;\r
349 case EmmcPartitionGP1:\r
350 GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[0] | (ExtCsd->GpSizeMult[1] << 8) | (ExtCsd->GpSizeMult[2] << 16));\r
351 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
352 break;\r
353 case EmmcPartitionGP2:\r
354 GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[3] | (ExtCsd->GpSizeMult[4] << 8) | (ExtCsd->GpSizeMult[5] << 16));\r
355 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
356 break;\r
357 case EmmcPartitionGP3:\r
358 GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[6] | (ExtCsd->GpSizeMult[7] << 8) | (ExtCsd->GpSizeMult[8] << 16));\r
359 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
360 break;\r
361 case EmmcPartitionGP4:\r
362 GpSizeMult = (UINT32)(ExtCsd->GpSizeMult[9] | (ExtCsd->GpSizeMult[10] << 8) | (ExtCsd->GpSizeMult[11] << 16));\r
363 Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);\r
364 break;\r
365 default:\r
366 ASSERT (FALSE);\r
367 return EFI_INVALID_PARAMETER;\r
368 }\r
369\r
370 if (Capacity != 0) {\r
371 Partition->Enable = TRUE;\r
372 Partition->BlockMedia.LastBlock = DivU64x32 (Capacity, Partition->BlockMedia.BlockSize) - 1;\r
373 }\r
374 }\r
375\r
376 return EFI_SUCCESS;\r
377}\r
378\r
379/**\r
380 Install BlkIo, BlkIo2 and Ssp protocols for the specified partition in the EMMC device.\r
381\r
382 @param[in] Device The pointer to the EMMC_DEVICE data structure.\r
383 @param[in] Index The index of the partition.\r
384\r
385 @retval EFI_SUCCESS The protocols are installed successfully.\r
386 @retval Others Some error occurs when installing the protocols.\r
387\r
388**/\r
389EFI_STATUS\r
390InstallProtocolOnPartition (\r
391 IN EMMC_DEVICE *Device,\r
392 IN UINT8 Index\r
393 )\r
394{\r
395 EFI_STATUS Status;\r
396 EMMC_PARTITION *Partition;\r
397 CONTROLLER_DEVICE_PATH ControlNode;\r
398 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
399 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
400 EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;\r
401 EFI_HANDLE DeviceHandle;\r
402\r
403 //\r
404 // Build device path\r
405 //\r
406 ParentDevicePath = Device->DevicePath;\r
407\r
408 ControlNode.Header.Type = HARDWARE_DEVICE_PATH;\r
409 ControlNode.Header.SubType = HW_CONTROLLER_DP;\r
410 SetDevicePathNodeLength (&ControlNode.Header, sizeof (CONTROLLER_DEVICE_PATH));\r
411 ControlNode.ControllerNumber = Index;\r
412\r
413 DevicePath = AppendDevicePathNode (ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*)&ControlNode);\r
414 if (DevicePath == NULL) {\r
415 Status = EFI_OUT_OF_RESOURCES;\r
416 goto Error;\r
417 }\r
418\r
419 DeviceHandle = NULL;\r
420 RemainingDevicePath = DevicePath;\r
421 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);\r
422 if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {\r
423 Status = EFI_ALREADY_STARTED;\r
424 goto Error;\r
425 }\r
426\r
427 Partition = &Device->Partition[Index];\r
428 Partition->DevicePath = DevicePath;\r
429 if (Partition->Enable) {\r
430 //\r
431 // Install BlkIo/BlkIo2/Ssp for the specified partition\r
432 //\r
433 Status = gBS->InstallMultipleProtocolInterfaces (\r
434 &Partition->Handle,\r
435 &gEfiDevicePathProtocolGuid,\r
436 Partition->DevicePath,\r
437 &gEfiBlockIoProtocolGuid,\r
438 &Partition->BlockIo,\r
439 &gEfiBlockIo2ProtocolGuid,\r
440 &Partition->BlockIo2,\r
441 NULL\r
442 );\r
443 if (EFI_ERROR (Status)) {\r
444 goto Error;\r
445 }\r
446\r
447 if (((Partition->PartitionType == EmmcPartitionUserData) ||\r
448 (Partition->PartitionType == EmmcPartitionBoot1) ||\r
449 (Partition->PartitionType == EmmcPartitionBoot2)) &&\r
450 ((Device->Csd.Ccc & BIT10) != 0)) {\r
451 Status = gBS->InstallProtocolInterface (\r
452 &Partition->Handle,\r
453 &gEfiStorageSecurityCommandProtocolGuid,\r
454 EFI_NATIVE_INTERFACE,\r
455 &Partition->StorageSecurity\r
456 );\r
457 if (EFI_ERROR (Status)) {\r
458 gBS->UninstallMultipleProtocolInterfaces (\r
459 &Partition->Handle,\r
460 &gEfiDevicePathProtocolGuid,\r
461 Partition->DevicePath,\r
462 &gEfiBlockIoProtocolGuid,\r
463 &Partition->BlockIo,\r
464 &gEfiBlockIo2ProtocolGuid,\r
465 &Partition->BlockIo2,\r
466 NULL\r
467 );\r
468 goto Error;\r
469 }\r
470 }\r
471\r
472 gBS->OpenProtocol (\r
473 Device->Private->Controller,\r
474 &gEfiSdMmcPassThruProtocolGuid,\r
475 (VOID **) &(Device->Private->PassThru),\r
476 Device->Private->DriverBindingHandle,\r
477 Partition->Handle,\r
478 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
479 );\r
480 } else {\r
481 Status = EFI_INVALID_PARAMETER;\r
482 }\r
483\r
484Error:\r
485 if (EFI_ERROR (Status) && (DevicePath != NULL)) {\r
486 FreePool (DevicePath);\r
487 }\r
488\r
489 return Status;\r
490}\r
491\r
492/**\r
493 Scan EMMC Bus to discover the device.\r
494\r
495 @param[in] Private The EMMC driver private data structure.\r
496 @param[in] Slot The slot number to check device present.\r
497\r
498 @retval EFI_SUCCESS Successfully to discover the device and attach\r
499 SdMmcIoProtocol to it.\r
500 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack\r
501 of resources.\r
502 @retval EFI_ALREADY_STARTED The device was discovered before.\r
503 @retval Others Fail to discover the device.\r
504\r
505**/\r
506EFI_STATUS\r
507EFIAPI\r
508DiscoverEmmcDevice (\r
509 IN EMMC_DRIVER_PRIVATE_DATA *Private,\r
510 IN UINT8 Slot,\r
511 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
512 )\r
513{\r
514 EFI_STATUS Status;\r
515 EMMC_DEVICE *Device;\r
516 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
517 EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
518 EFI_DEVICE_PATH_PROTOCOL *RemainingEmmcDevPath;\r
519 EFI_DEV_PATH *Node;\r
520 EFI_HANDLE DeviceHandle;\r
521 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
522 UINT8 Index;\r
523\r
524 Device = NULL;\r
525 DevicePath = NULL;\r
526 NewDevicePath = NULL;\r
527 RemainingDevicePath = NULL;\r
528 PassThru = Private->PassThru;\r
529 Device = &Private->Device[Slot];\r
530\r
531 //\r
532 // Build Device Path to check if the EMMC device present at the slot.\r
533 //\r
534 Status = PassThru->BuildDevicePath (\r
535 PassThru,\r
536 Slot,\r
537 &DevicePath\r
538 );\r
539 if (EFI_ERROR(Status)) {\r
540 return Status;\r
541 }\r
542\r
543 if (DevicePath->SubType != MSG_EMMC_DP) {\r
544 Status = EFI_UNSUPPORTED;\r
545 goto Error;\r
546 }\r
547\r
548 NewDevicePath = AppendDevicePathNode (\r
549 Private->ParentDevicePath,\r
550 DevicePath\r
551 );\r
552 if (NewDevicePath == NULL) {\r
553 Status = EFI_OUT_OF_RESOURCES;\r
554 goto Error;\r
555 }\r
556\r
557 DeviceHandle = NULL;\r
558 RemainingEmmcDevPath = NewDevicePath;\r
559 Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingEmmcDevPath, &DeviceHandle);\r
560 //\r
561 // The device path to the EMMC device doesn't exist. It means the corresponding device private data hasn't been initialized.\r
562 //\r
563 if (EFI_ERROR (Status) || (DeviceHandle == NULL) || !IsDevicePathEnd (RemainingEmmcDevPath)) {\r
564 Device->DevicePath = NewDevicePath;\r
565 Device->Slot = Slot;\r
566 Device->Private = Private;\r
567 //\r
568 // Expose user area in the Sd memory card to upper layer.\r
569 //\r
570 Status = DiscoverAllPartitions (Device);\r
571 if (EFI_ERROR(Status)) {\r
572 FreePool (NewDevicePath);\r
573 goto Error;\r
574 }\r
575\r
576 Status = gBS->InstallProtocolInterface (\r
577 &Device->Handle,\r
578 &gEfiDevicePathProtocolGuid,\r
579 EFI_NATIVE_INTERFACE,\r
580 Device->DevicePath\r
581 );\r
582 if (EFI_ERROR(Status)) {\r
583 FreePool (NewDevicePath);\r
584 goto Error;\r
585 }\r
586\r
587 Device->ControllerNameTable = NULL;\r
588 GetEmmcModelName (Device, &Device->Cid);\r
589 AddUnicodeString2 (\r
590 "eng",\r
591 gEmmcDxeComponentName.SupportedLanguages,\r
592 &Device->ControllerNameTable,\r
593 Device->ModelName,\r
594 TRUE\r
595 );\r
596 AddUnicodeString2 (\r
597 "en",\r
598 gEmmcDxeComponentName.SupportedLanguages,\r
599 &Device->ControllerNameTable,\r
600 Device->ModelName,\r
601 FALSE\r
602 );\r
603 }\r
604\r
605 if (RemainingDevicePath == NULL) {\r
606 //\r
607 // Expose all partitions in the Emmc device to upper layer.\r
608 //\r
609 for (Index = 0; Index < EMMC_MAX_PARTITIONS; Index++) {\r
610 InstallProtocolOnPartition (Device, Index);\r
611 }\r
612 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
613 //\r
614 // Enumerate the specified partition\r
615 //\r
616 Node = (EFI_DEV_PATH *) RemainingDevicePath;\r
617 if ((DevicePathType (&Node->DevPath) != HARDWARE_DEVICE_PATH) ||\r
618 (DevicePathSubType (&Node->DevPath) != HW_CONTROLLER_DP) ||\r
619 (DevicePathNodeLength (&Node->DevPath) != sizeof (CONTROLLER_DEVICE_PATH))) {\r
620 Status = EFI_INVALID_PARAMETER;\r
621 goto Error;\r
622 }\r
623\r
624 Index = (UINT8)Node->Controller.ControllerNumber;\r
625 if (Index >= EMMC_MAX_PARTITIONS) {\r
626 Status = EFI_INVALID_PARAMETER;\r
627 goto Error;\r
628 }\r
629\r
630 Status = InstallProtocolOnPartition (Device, Index);\r
631 }\r
632\r
633Error:\r
634 FreePool (DevicePath);\r
635\r
636 return Status;\r
637}\r
638\r
639/**\r
640 Tests to see if this driver supports a given controller. If a child device is provided,\r
641 it further tests to see if this driver supports creating a handle for the specified child device.\r
642\r
643 This function checks to see if the driver specified by This supports the device specified by\r
644 ControllerHandle. Drivers will typically use the device path attached to\r
645 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
646 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
647 may be called many times during platform initialization. In order to reduce boot times, the tests\r
648 performed by this function must be very small, and take as little time as possible to execute. This\r
649 function must not change the state of any hardware devices, and this function must be aware that the\r
650 device specified by ControllerHandle may already be managed by the same driver or a\r
651 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
652 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
653 Since ControllerHandle may have been previously started by the same driver, if a protocol is\r
654 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
655 to guarantee the state of ControllerHandle is not modified by this function.\r
656\r
657 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
658 @param[in] ControllerHandle The handle of the controller to test. This handle\r
659 must support a protocol interface that supplies\r
660 an I/O abstraction to the driver.\r
661 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
662 parameter is ignored by device drivers, and is optional for bus\r
663 drivers. For bus drivers, if this parameter is not NULL, then\r
664 the bus driver must determine if the bus controller specified\r
665 by ControllerHandle and the child controller specified\r
666 by RemainingDevicePath are both supported by this\r
667 bus driver.\r
668\r
669 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
670 RemainingDevicePath is supported by the driver specified by This.\r
671 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
672 RemainingDevicePath is already being managed by the driver\r
673 specified by This.\r
674 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
675 RemainingDevicePath is already being managed by a different\r
676 driver or an application that requires exclusive access.\r
677 Currently not implemented.\r
678 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
679 RemainingDevicePath is not supported by the driver specified by This.\r
680**/\r
681EFI_STATUS\r
682EFIAPI\r
683EmmcDxeDriverBindingSupported (\r
684 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
685 IN EFI_HANDLE Controller,\r
686 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
687 )\r
688{\r
689 EFI_STATUS Status;\r
690 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
691 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
692 UINT8 Slot;\r
693\r
694 //\r
695 // Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.\r
696 //\r
697 Status = gBS->OpenProtocol (\r
698 Controller,\r
699 &gEfiSdMmcPassThruProtocolGuid,\r
700 (VOID**) &PassThru,\r
701 This->DriverBindingHandle,\r
702 Controller,\r
703 EFI_OPEN_PROTOCOL_BY_DRIVER\r
704 );\r
705\r
706 if (Status == EFI_ALREADY_STARTED) {\r
707 return EFI_SUCCESS;\r
708 }\r
709\r
710 if (EFI_ERROR (Status)) {\r
711 return Status;\r
712 }\r
713\r
714 //\r
715 // Test RemainingDevicePath is valid or not.\r
716 //\r
717 if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {\r
718 Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);\r
719 if (EFI_ERROR (Status)) {\r
720 //\r
721 // Close the I/O Abstraction(s) used to perform the supported test\r
722 //\r
723 gBS->CloseProtocol (\r
724 Controller,\r
725 &gEfiSdMmcPassThruProtocolGuid,\r
726 This->DriverBindingHandle,\r
727 Controller\r
728 );\r
729 return Status;\r
730 }\r
731 }\r
732\r
733 //\r
734 // Close the I/O Abstraction(s) used to perform the supported test\r
735 //\r
736 gBS->CloseProtocol (\r
737 Controller,\r
738 &gEfiSdMmcPassThruProtocolGuid,\r
739 This->DriverBindingHandle,\r
740 Controller\r
741 );\r
742\r
743 //\r
744 // Open the EFI Device Path protocol needed to perform the supported test\r
745 //\r
746 Status = gBS->OpenProtocol (\r
747 Controller,\r
748 &gEfiDevicePathProtocolGuid,\r
749 (VOID **) &ParentDevicePath,\r
750 This->DriverBindingHandle,\r
751 Controller,\r
752 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
753 );\r
754 return Status;\r
755}\r
756\r
757/**\r
758 Starts a device controller or a bus controller.\r
759\r
760 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
761 As a result, much of the error checking on the parameters to Start() has been moved into this\r
762 common boot service. It is legal to call Start() from other locations,\r
763 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
764 1. ControllerHandle must be a valid EFI_HANDLE.\r
765 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
766 EFI_DEVICE_PATH_PROTOCOL.\r
767 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
768 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
769\r
770 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
771 @param[in] ControllerHandle The handle of the controller to start. This handle\r
772 must support a protocol interface that supplies\r
773 an I/O abstraction to the driver.\r
774 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
775 parameter is ignored by device drivers, and is optional for bus\r
776 drivers. For a bus driver, if this parameter is NULL, then handles\r
777 for all the children of Controller are created by this driver.\r
778 If this parameter is not NULL and the first Device Path Node is\r
779 not the End of Device Path Node, then only the handle for the\r
780 child device specified by the first Device Path Node of\r
781 RemainingDevicePath is created by this driver.\r
782 If the first Device Path Node of RemainingDevicePath is\r
783 the End of Device Path Node, no child handle is created by this\r
784 driver.\r
785\r
786 @retval EFI_SUCCESS The device was started.\r
787 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
788 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
789 @retval Others The driver failded to start the device.\r
790\r
791**/\r
792EFI_STATUS\r
793EFIAPI\r
794EmmcDxeDriverBindingStart (\r
795 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
796 IN EFI_HANDLE Controller,\r
797 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
798 )\r
799{\r
800 EFI_STATUS Status;\r
801 EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;\r
802 EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
803 EMMC_DRIVER_PRIVATE_DATA *Private;\r
804 UINT8 Slot;\r
805\r
806 Private = NULL;\r
807 PassThru = NULL;\r
808 Status = gBS->OpenProtocol (\r
809 Controller,\r
810 &gEfiSdMmcPassThruProtocolGuid,\r
811 (VOID **) &PassThru,\r
812 This->DriverBindingHandle,\r
813 Controller,\r
814 EFI_OPEN_PROTOCOL_BY_DRIVER\r
815 );\r
816 if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {\r
817 return Status;\r
818 }\r
819\r
820 //\r
821 // Check EFI_ALREADY_STARTED to reuse the original EMMC_DRIVER_PRIVATE_DATA.\r
822 //\r
823 if (Status != EFI_ALREADY_STARTED) {\r
824 Private = AllocateZeroPool (sizeof (EMMC_DRIVER_PRIVATE_DATA));\r
825 if (Private == NULL) {\r
826 Status = EFI_OUT_OF_RESOURCES;\r
827 goto Error;\r
828 }\r
829\r
830 Status = gBS->OpenProtocol (\r
831 Controller,\r
832 &gEfiDevicePathProtocolGuid,\r
833 (VOID **) &ParentDevicePath,\r
834 This->DriverBindingHandle,\r
835 Controller,\r
836 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
837 );\r
838 ASSERT_EFI_ERROR (Status);\r
839 Private->PassThru = PassThru;\r
840 Private->Controller = Controller;\r
841 Private->ParentDevicePath = ParentDevicePath;\r
842 Private->DriverBindingHandle = This->DriverBindingHandle;\r
843\r
844 Status = gBS->InstallProtocolInterface (\r
845 &Controller,\r
846 &gEfiCallerIdGuid,\r
847 EFI_NATIVE_INTERFACE,\r
848 Private\r
849 );\r
850 if (EFI_ERROR (Status)) {\r
851 goto Error;\r
852 }\r
853 } else {\r
854 Status = gBS->OpenProtocol (\r
855 Controller,\r
856 &gEfiCallerIdGuid,\r
857 (VOID **) &Private,\r
858 This->DriverBindingHandle,\r
859 Controller,\r
860 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
861 );\r
862 if (EFI_ERROR (Status)) {\r
863 goto Error;\r
864 }\r
865 }\r
866\r
867 if (RemainingDevicePath == NULL) {\r
868 Slot = 0xFF;\r
869 while (TRUE) {\r
870 Status = PassThru->GetNextSlot (PassThru, &Slot);\r
871 if (EFI_ERROR (Status)) {\r
872 //\r
873 // Cannot find more legal slots.\r
874 //\r
875 Status = EFI_SUCCESS;\r
876 break;\r
877 }\r
878\r
879 Status = DiscoverEmmcDevice (Private, Slot, NULL);\r
880 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
881 break;\r
882 }\r
883 }\r
884 } else if (!IsDevicePathEnd (RemainingDevicePath)) {\r
885 Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);\r
886 if (!EFI_ERROR (Status)) {\r
887 Status = DiscoverEmmcDevice (Private, Slot, NextDevicePathNode (RemainingDevicePath));\r
888 }\r
889 }\r
890\r
891Error:\r
892 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
893 gBS->CloseProtocol (\r
894 Controller,\r
895 &gEfiSdMmcPassThruProtocolGuid,\r
896 This->DriverBindingHandle,\r
897 Controller\r
898 );\r
899\r
900 if (Private != NULL) {\r
901 gBS->UninstallMultipleProtocolInterfaces (\r
902 Controller,\r
903 &gEfiCallerIdGuid,\r
904 Private,\r
905 NULL\r
906 );\r
907 FreePool (Private);\r
908 }\r
909 }\r
910 return Status;\r
911}\r
912\r
913/**\r
914 Stops a device controller or a bus controller.\r
915\r
916 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
917 As a result, much of the error checking on the parameters to Stop() has been moved\r
918 into this common boot service. It is legal to call Stop() from other locations,\r
919 but the following calling restrictions must be followed or the system behavior will not be deterministic.\r
920 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
921 same driver's Start() function.\r
922 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
923 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
924 Start() function, and the Start() function must have called OpenProtocol() on\r
925 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
926\r
927 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
928 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
929 support a bus specific I/O protocol for the driver\r
930 to use to stop the device.\r
931 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
932 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
933 if NumberOfChildren is 0.\r
934\r
935 @retval EFI_SUCCESS The device was stopped.\r
936 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
937\r
938**/\r
939EFI_STATUS\r
940EFIAPI\r
941EmmcDxeDriverBindingStop (\r
942 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
943 IN EFI_HANDLE Controller,\r
944 IN UINTN NumberOfChildren,\r
945 IN EFI_HANDLE *ChildHandleBuffer\r
946 )\r
947{\r
948 EFI_STATUS Status;\r
949 BOOLEAN AllChildrenStopped;\r
950 UINTN Index;\r
951 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
952 EMMC_DRIVER_PRIVATE_DATA *Private;\r
953 EMMC_DEVICE *Device;\r
954 EMMC_PARTITION *Partition;\r
955 EFI_BLOCK_IO_PROTOCOL *BlockIo;\r
956 EFI_BLOCK_IO2_PROTOCOL *BlockIo2;\r
957 EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *StorageSecurity;\r
958 LIST_ENTRY *Link;\r
959 LIST_ENTRY *NextLink;\r
960 EMMC_REQUEST *Request;\r
961\r
962 BlockIo = NULL;\r
963 BlockIo2 = NULL;\r
964 if (NumberOfChildren == 0) {\r
965 Status = gBS->OpenProtocol (\r
966 Controller,\r
967 &gEfiCallerIdGuid,\r
968 (VOID **) &Private,\r
969 This->DriverBindingHandle,\r
970 Controller,\r
971 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
972 );\r
973 if (EFI_ERROR (Status)) {\r
974 return EFI_DEVICE_ERROR;\r
975 }\r
976\r
977 for (Index = 0; Index < EMMC_MAX_DEVICES; Index++) {\r
978 Device = &Private->Device[Index];\r
979 Status = gBS->OpenProtocol (\r
980 Device->Handle,\r
981 &gEfiDevicePathProtocolGuid,\r
982 (VOID **) &DevicePath,\r
983 This->DriverBindingHandle,\r
984 Controller,\r
985 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
986 );\r
987 if (EFI_ERROR (Status)) {\r
988 continue;\r
989 }\r
990 ASSERT (DevicePath == Device->DevicePath);\r
991 gBS->UninstallProtocolInterface (\r
992 Device->Handle,\r
993 &gEfiDevicePathProtocolGuid,\r
994 DevicePath\r
995 );\r
996 FreePool (Device->DevicePath);\r
997 }\r
998\r
999 gBS->UninstallProtocolInterface (\r
1000 Controller,\r
1001 &gEfiCallerIdGuid,\r
1002 Private\r
1003 );\r
1004 gBS->CloseProtocol (\r
1005 Controller,\r
1006 &gEfiSdMmcPassThruProtocolGuid,\r
1007 This->DriverBindingHandle,\r
1008 Controller\r
1009 );\r
1010 FreePool (Private);\r
1011\r
1012 return EFI_SUCCESS;\r
1013 }\r
1014\r
1015 AllChildrenStopped = TRUE;\r
1016\r
1017 for (Index = 0; Index < NumberOfChildren; Index++) {\r
1018 Status = gBS->OpenProtocol (\r
1019 ChildHandleBuffer[Index],\r
1020 &gEfiBlockIoProtocolGuid,\r
1021 (VOID **) &BlockIo,\r
1022 This->DriverBindingHandle,\r
1023 Controller,\r
1024 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1025 );\r
1026 if (EFI_ERROR (Status)) {\r
1027 Status = gBS->OpenProtocol (\r
1028 ChildHandleBuffer[Index],\r
1029 &gEfiBlockIo2ProtocolGuid,\r
1030 (VOID **) &BlockIo2,\r
1031 This->DriverBindingHandle,\r
1032 Controller,\r
1033 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1034 );\r
1035 if (EFI_ERROR (Status)) {\r
1036 AllChildrenStopped = FALSE;\r
1037 continue;\r
1038 }\r
1039 }\r
1040\r
1041 if (BlockIo != NULL) {\r
1042 Partition = EMMC_PARTITION_DATA_FROM_BLKIO (BlockIo);\r
1043 } else {\r
1044 ASSERT (BlockIo2 != NULL);\r
1045 Partition = EMMC_PARTITION_DATA_FROM_BLKIO2 (BlockIo2);\r
1046 }\r
1047\r
1048 for (Link = GetFirstNode (&Partition->Queue);\r
1049 !IsNull (&Partition->Queue, Link);\r
1050 Link = NextLink) {\r
1051 NextLink = GetNextNode (&Partition->Queue, Link);\r
1052\r
1053 RemoveEntryList (Link);\r
1054 Request = EMMC_REQUEST_FROM_LINK (Link);\r
1055\r
1056 gBS->CloseEvent (Request->Event);\r
1057 Request->Token->TransactionStatus = EFI_ABORTED;\r
1058\r
1059 if (Request->IsEnd) {\r
1060 gBS->SignalEvent (Request->Token->Event);\r
1061 }\r
1062\r
1063 FreePool (Request);\r
1064 }\r
1065\r
1066 //\r
1067 // Close the child handle\r
1068 //\r
1069 Status = gBS->CloseProtocol (\r
1070 Controller,\r
1071 &gEfiSdMmcPassThruProtocolGuid,\r
1072 This->DriverBindingHandle,\r
1073 ChildHandleBuffer[Index]\r
1074 );\r
1075\r
1076 Status = gBS->UninstallMultipleProtocolInterfaces (\r
1077 ChildHandleBuffer[Index],\r
1078 &gEfiDevicePathProtocolGuid,\r
1079 Partition->DevicePath,\r
1080 &gEfiBlockIoProtocolGuid,\r
1081 &Partition->BlockIo,\r
1082 &gEfiBlockIo2ProtocolGuid,\r
1083 &Partition->BlockIo2,\r
1084 NULL\r
1085 );\r
1086 if (EFI_ERROR (Status)) {\r
1087 AllChildrenStopped = FALSE;\r
1088 gBS->OpenProtocol (\r
1089 Controller,\r
1090 &gEfiSdMmcPassThruProtocolGuid,\r
1091 (VOID **)&Partition->Device->Private->PassThru,\r
1092 This->DriverBindingHandle,\r
1093 ChildHandleBuffer[Index],\r
1094 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1095 );\r
1096 continue;\r
1097 }\r
1098\r
1099 //\r
1100 // If Storage Security Command Protocol is installed, then uninstall this protocol.\r
1101 //\r
1102 Status = gBS->OpenProtocol (\r
1103 ChildHandleBuffer[Index],\r
1104 &gEfiStorageSecurityCommandProtocolGuid,\r
1105 (VOID **) &StorageSecurity,\r
1106 This->DriverBindingHandle,\r
1107 Controller,\r
1108 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1109 );\r
1110\r
1111 if (!EFI_ERROR (Status)) {\r
1112 Status = gBS->UninstallProtocolInterface (\r
1113 ChildHandleBuffer[Index],\r
1114 &gEfiStorageSecurityCommandProtocolGuid,\r
1115 &Partition->StorageSecurity\r
1116 );\r
1117 if (EFI_ERROR (Status)) {\r
1118 gBS->OpenProtocol (\r
1119 Controller,\r
1120 &gEfiSdMmcPassThruProtocolGuid,\r
1121 (VOID **) &Partition->Device->Private->PassThru,\r
1122 This->DriverBindingHandle,\r
1123 ChildHandleBuffer[Index],\r
1124 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1125 );\r
1126 AllChildrenStopped = FALSE;\r
1127 continue;\r
1128 }\r
1129 }\r
1130\r
1131 FreePool (Partition->DevicePath);\r
1132 }\r
1133\r
1134 if (!AllChildrenStopped) {\r
1135 return EFI_DEVICE_ERROR;\r
1136 }\r
1137\r
1138 return EFI_SUCCESS;\r
1139}\r
1140\r
1141/**\r
1142 The user Entry Point for module EmmcDxe. The user code starts with this function.\r
1143\r
1144 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
1145 @param[in] SystemTable A pointer to the EFI System Table.\r
1146\r
1147 @retval EFI_SUCCESS The entry point is executed successfully.\r
1148 @retval other Some errors occur when executing this entry point.\r
1149\r
1150**/\r
1151EFI_STATUS\r
1152EFIAPI\r
1153InitializeEmmcDxe (\r
1154 IN EFI_HANDLE ImageHandle,\r
1155 IN EFI_SYSTEM_TABLE *SystemTable\r
1156 )\r
1157{\r
1158 EFI_STATUS Status;\r
1159\r
1160 //\r
1161 // Install driver model protocol(s).\r
1162 //\r
1163 Status = EfiLibInstallDriverBindingComponentName2 (\r
1164 ImageHandle,\r
1165 SystemTable,\r
1166 &gEmmcDxeDriverBinding,\r
1167 ImageHandle,\r
1168 &gEmmcDxeComponentName,\r
1169 &gEmmcDxeComponentName2\r
1170 );\r
1171 ASSERT_EFI_ERROR (Status);\r
1172\r
1173 return Status;\r
1174}\r
1175\r