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