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