Patch from open source community for CryptoPkg to allow it to build for ARM using...
[mirror_edk2.git] / ArmPkg / Universal / MmcDxe / Mmc.c
CommitLineData
1bfda055 1/** @file\r
2 Main file of the MMC Dxe driver. The driver entrypoint is defined into this file.\r
3\r
4 Copyright (c) 2011, ARM Limited. All rights reserved.\r
5 \r
6 This program and the accompanying materials \r
7 are licensed and made available under the terms and conditions of the BSD License \r
8 which accompanies this distribution. The full text of the license may be found at \r
9 http://opensource.org/licenses/bsd-license.php \r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include <Protocol/DevicePath.h>\r
17#include <Protocol/MmcHost.h>\r
18\r
19#include <Library/BaseLib.h>\r
20#include <Library/BaseMemoryLib.h>\r
21#include <Library/MemoryAllocationLib.h>\r
22#include <Library/UefiBootServicesTableLib.h>\r
23#include <Library/DevicePathLib.h>\r
24#include <Library/DebugLib.h>\r
25\r
26#include "Mmc.h"\r
27\r
28EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {\r
29 SIGNATURE_32('m','m','c','o'), // MediaId\r
30 TRUE, // RemovableMedia\r
31 FALSE, // MediaPresent\r
32 FALSE, // LogicalPartition\r
33 FALSE, // ReadOnly\r
34 FALSE, // WriteCaching\r
35 512, // BlockSize\r
36 4, // IoAlign\r
37 0, // Pad\r
38 0 // LastBlock\r
39};\r
40\r
41//\r
42// This device structure is serviced as a header.\r
43// Its next field points to the first root bridge device node.\r
44//\r
45LIST_ENTRY mMmcHostPool;\r
46\r
47/**\r
48 Initialize the MMC Host Pool to support multiple MMC devices\r
49**/\r
50VOID\r
51InitializeMmcHostPool (\r
52 VOID\r
53 )\r
54{\r
55 InitializeListHead (&mMmcHostPool);\r
56}\r
57\r
58/**\r
59 Insert a new Mmc Host controller to the pool\r
60**/\r
61VOID\r
62InsertMmcHost (\r
63 IN MMC_HOST_INSTANCE *MmcHostInstance\r
64 )\r
65{\r
66 InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
67}\r
68\r
69/*\r
70 Remove a new Mmc Host controller to the pool\r
71*/\r
72VOID\r
73RemoveMmcHost (\r
74 IN MMC_HOST_INSTANCE *MmcHostInstance\r
75 )\r
76{\r
77 RemoveEntryList (&(MmcHostInstance->Link));\r
78}\r
79\r
80MMC_HOST_INSTANCE* CreateMmcHostInstance(\r
81 IN EFI_MMC_HOST_PROTOCOL* MmcHost\r
82 )\r
83{\r
84 EFI_STATUS Status;\r
85 MMC_HOST_INSTANCE* MmcHostInstance;\r
86 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
87 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
88\r
89 MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
90 if (MmcHostInstance == NULL) {\r
91 return NULL;\r
92 }\r
93\r
94 MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
95\r
96 MmcHostInstance->State = MmcHwInitializationState;\r
97 \r
98 MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);\r
99 if (MmcHostInstance->BlockIo.Media == NULL) {\r
100 goto FREE_INSTANCE;\r
101 }\r
102\r
103 MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;\r
104 MmcHostInstance->BlockIo.Reset = MmcReset;\r
105 MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;\r
106 MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;\r
107 MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;\r
108\r
109 MmcHostInstance->MmcHost = MmcHost;\r
110\r
111 // Create DevicePath for the new MMC Host\r
112 Status = MmcHost->BuildDevicePath(&NewDevicePathNode);\r
113 if (EFI_ERROR (Status)) {\r
114 goto FREE_MEDIA;\r
115 }\r
116\r
117 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
118 if (DevicePath == NULL) {\r
119 goto FREE_MEDIA;\r
120 }\r
121 \r
122 SetDevicePathEndNode (DevicePath);\r
123 MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);\r
124\r
125 // Publish BlockIO protocol interface\r
126 Status = gBS->InstallMultipleProtocolInterfaces (\r
127 &MmcHostInstance->MmcHandle,\r
128 &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
129 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
130 NULL\r
131 );\r
132 if (EFI_ERROR(Status)) {\r
133 goto FREE_DEVICE_PATH;\r
134 }\r
135\r
136 return MmcHostInstance;\r
137\r
138FREE_DEVICE_PATH:\r
139 FreePool(DevicePath);\r
140\r
141FREE_MEDIA:\r
142 FreePool(MmcHostInstance->BlockIo.Media);\r
143\r
144FREE_INSTANCE:\r
145 FreePool(MmcHostInstance);\r
146\r
147 return NULL;\r
148}\r
149\r
150EFI_STATUS DestroyMmcHostInstance(\r
151 IN MMC_HOST_INSTANCE* MmcHostInstance\r
152 )\r
153{\r
154 EFI_STATUS Status;\r
155\r
156 // Uninstall Protocol Interfaces\r
157 Status = gBS->UninstallMultipleProtocolInterfaces(\r
6102636a 158 MmcHostInstance->MmcHandle,\r
1bfda055 159 &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
6102636a 160 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
1bfda055 161 NULL\r
162 );\r
163 ASSERT_EFI_ERROR (Status);\r
164 \r
165 // Free Memory allocated for the instance\r
166 if (MmcHostInstance->BlockIo.Media) {\r
167 FreePool(MmcHostInstance->BlockIo.Media);\r
168 }\r
169 FreePool (MmcHostInstance);\r
170\r
171 return Status;\r
172}\r
173\r
174/**\r
175 This function checks if the controller implement the Mmc Host and the Device Path Protocols\r
176**/\r
177EFI_STATUS\r
178EFIAPI\r
179MmcDriverBindingSupported (\r
180 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
181 IN EFI_HANDLE Controller,\r
182 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
183 )\r
184{\r
185 EFI_STATUS Status;\r
186 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
187 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
188 EFI_DEV_PATH_PTR Node;\r
189\r
190 //\r
191 // Check RemainingDevicePath validation\r
192 //\r
193 if (RemainingDevicePath != NULL) {\r
194 //\r
195 // Check if RemainingDevicePath is the End of Device Path Node, \r
196 // if yes, go on checking other conditions\r
197 //\r
198 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
199 //\r
200 // If RemainingDevicePath isn't the End of Device Path Node,\r
201 // check its validation\r
202 //\r
203 Node.DevPath = RemainingDevicePath;\r
204 if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
205 Node.DevPath->SubType != HW_VENDOR_DP ||\r
206 DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {\r
207 return EFI_UNSUPPORTED;\r
208 }\r
209 }\r
210 }\r
211\r
212 //\r
213 // Check if Mmc Host protocol is installed by platform\r
214 //\r
215 Status = gBS->OpenProtocol (\r
216 Controller,\r
217 &gEfiMmcHostProtocolGuid,\r
218 (VOID **) &MmcHost,\r
219 This->DriverBindingHandle,\r
220 Controller,\r
221 EFI_OPEN_PROTOCOL_BY_DRIVER\r
222 );\r
223 if (Status == EFI_ALREADY_STARTED) {\r
224 return EFI_SUCCESS;\r
225 }\r
226 if (EFI_ERROR (Status)) {\r
227 return Status;\r
228 }\r
229\r
230 //\r
231 // Close the Mmc Host used to perform the supported test\r
232 //\r
233 gBS->CloseProtocol (\r
234 Controller,\r
235 &gEfiMmcHostProtocolGuid,\r
236 This->DriverBindingHandle,\r
237 Controller\r
238 );\r
239\r
240 return EFI_SUCCESS;\r
241}\r
242\r
243/**\r
244 \r
245**/\r
246EFI_STATUS\r
247EFIAPI\r
248MmcDriverBindingStart (\r
249 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
250 IN EFI_HANDLE Controller,\r
251 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
252 )\r
253{\r
254 EFI_STATUS Status;\r
255 MMC_HOST_INSTANCE *MmcHostInstance;\r
256 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
257\r
258 //\r
259 // Check RemainingDevicePath validation\r
260 //\r
261 if (RemainingDevicePath != NULL) {\r
262 //\r
263 // Check if RemainingDevicePath is the End of Device Path Node, \r
264 // if yes, return EFI_SUCCESS\r
265 //\r
266 if (IsDevicePathEnd (RemainingDevicePath)) {\r
267 return EFI_SUCCESS;\r
268 }\r
269 }\r
270\r
271 //\r
272 // Get the Mmc Host protocol\r
273 //\r
274 Status = gBS->OpenProtocol (\r
275 Controller,\r
276 &gEfiMmcHostProtocolGuid,\r
277 (VOID **) &MmcHost,\r
278 This->DriverBindingHandle,\r
279 Controller,\r
280 EFI_OPEN_PROTOCOL_BY_DRIVER\r
281 );\r
282 if (EFI_ERROR (Status)) {\r
283 if (Status == EFI_ALREADY_STARTED) {\r
284 return EFI_SUCCESS;\r
285 }\r
286 return Status;\r
287 }\r
288\r
289 MmcHostInstance = CreateMmcHostInstance(MmcHost);\r
290 if (MmcHostInstance != NULL) {\r
291 // Add the handle to the pool\r
292 InsertMmcHost (MmcHostInstance);\r
293 }\r
294\r
295 return EFI_SUCCESS;\r
296}\r
297\r
298/**\r
299 \r
300**/\r
301EFI_STATUS\r
302EFIAPI\r
303MmcDriverBindingStop (\r
304 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
305 IN EFI_HANDLE Controller,\r
306 IN UINTN NumberOfChildren,\r
307 IN EFI_HANDLE *ChildHandleBuffer\r
308 )\r
309{\r
310 EFI_STATUS Status = EFI_SUCCESS;\r
311 LIST_ENTRY *CurrentLink;\r
312 MMC_HOST_INSTANCE *MmcHostInstance;\r
313\r
314 MMC_TRACE("MmcDriverBindingStop()");\r
315\r
316 // For each MMC instance\r
317 CurrentLink = mMmcHostPool.ForwardLink;\r
318 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
319 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
320 ASSERT(MmcHostInstance != NULL);\r
321\r
322 // Close gEfiMmcHostProtocolGuid\r
323 Status = gBS->CloseProtocol (\r
324 Controller,\r
325 &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost,\r
326 This->DriverBindingHandle\r
327 );\r
328\r
329 // Remove MMC Host Instance from the pool\r
330 RemoveMmcHost (MmcHostInstance);\r
331\r
332 // Destroy MmcHostInstance\r
333 DestroyMmcHostInstance (MmcHostInstance);\r
334 }\r
335\r
336 return Status;\r
337}\r
338\r
339EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
340 MmcDriverBindingSupported,\r
341 MmcDriverBindingStart,\r
342 MmcDriverBindingStop,\r
343 0xa,\r
344 NULL,\r
345 NULL\r
346};\r
347\r
348/**\r
349 \r
350**/\r
351EFI_STATUS\r
352EFIAPI\r
353MmcDxeInitialize (\r
354 IN EFI_HANDLE ImageHandle,\r
355 IN EFI_SYSTEM_TABLE *SystemTable\r
356 )\r
357{\r
358 EFI_STATUS Status;\r
359\r
360 //\r
361 // Initializes MMC Host pool\r
362 //\r
363 InitializeMmcHostPool ();\r
364\r
365 //\r
366 // Install driver model protocol(s).\r
367 //\r
368 Status = EfiLibInstallDriverBindingComponentName2 (\r
369 ImageHandle,\r
370 SystemTable,\r
371 &gMmcDriverBinding,\r
372 ImageHandle,\r
373 &gMmcComponentName,\r
374 &gMmcComponentName2\r
375 );\r
376 ASSERT_EFI_ERROR (Status);\r
377\r
378 // Install driver diagnostics\r
379 Status = gBS->InstallMultipleProtocolInterfaces (\r
380 &ImageHandle, \r
381 &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,\r
382 NULL\r
383 );\r
384 ASSERT_EFI_ERROR (Status);\r
385\r
386 return Status;\r
387}\r