]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Universal/MmcDxe/Mmc.c
MmcDxe Diagnostics: return EFI_UNSUPPORTED for Language other than english
[mirror_edk2.git] / EmbeddedPkg / 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
4ca3c688 4 Copyright (c) 2011-2013, ARM Limited. All rights reserved.\r
1bfda055 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
1bfda055 17\r
18#include <Library/BaseLib.h>\r
19#include <Library/BaseMemoryLib.h>\r
20#include <Library/MemoryAllocationLib.h>\r
21#include <Library/UefiBootServicesTableLib.h>\r
22#include <Library/DevicePathLib.h>\r
1bfda055 23\r
24#include "Mmc.h"\r
25\r
26EFI_BLOCK_IO_MEDIA mMmcMediaTemplate = {\r
27 SIGNATURE_32('m','m','c','o'), // MediaId\r
28 TRUE, // RemovableMedia\r
29 FALSE, // MediaPresent\r
30 FALSE, // LogicalPartition\r
31 FALSE, // ReadOnly\r
32 FALSE, // WriteCaching\r
33 512, // BlockSize\r
34 4, // IoAlign\r
35 0, // Pad\r
36 0 // LastBlock\r
37};\r
38\r
39//\r
40// This device structure is serviced as a header.\r
41// Its next field points to the first root bridge device node.\r
42//\r
43LIST_ENTRY mMmcHostPool;\r
44\r
3de99375 45/**\r
46 Event triggered by the timer to check if any cards have been removed\r
47 or if new ones have been plugged in\r
48**/\r
49\r
50EFI_EVENT gCheckCardsEvent;\r
51\r
1bfda055 52/**\r
53 Initialize the MMC Host Pool to support multiple MMC devices\r
54**/\r
55VOID\r
56InitializeMmcHostPool (\r
57 VOID\r
58 )\r
59{\r
e8e95df4 60 InitializeListHead (&mMmcHostPool);\r
1bfda055 61}\r
62\r
63/**\r
64 Insert a new Mmc Host controller to the pool\r
65**/\r
66VOID\r
67InsertMmcHost (\r
68 IN MMC_HOST_INSTANCE *MmcHostInstance\r
69 )\r
70{\r
e8e95df4 71 InsertTailList (&mMmcHostPool, &(MmcHostInstance->Link));\r
1bfda055 72}\r
73\r
74/*\r
75 Remove a new Mmc Host controller to the pool\r
76*/\r
77VOID\r
78RemoveMmcHost (\r
79 IN MMC_HOST_INSTANCE *MmcHostInstance\r
80 )\r
81{\r
e8e95df4 82 RemoveEntryList (&(MmcHostInstance->Link));\r
1bfda055 83}\r
84\r
e8e95df4 85MMC_HOST_INSTANCE* CreateMmcHostInstance (\r
1bfda055 86 IN EFI_MMC_HOST_PROTOCOL* MmcHost\r
87 )\r
88{\r
e8e95df4 89 EFI_STATUS Status;\r
90 MMC_HOST_INSTANCE* MmcHostInstance;\r
91 EFI_DEVICE_PATH_PROTOCOL *NewDevicePathNode;\r
92 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
1bfda055 93\r
e8e95df4 94 MmcHostInstance = AllocateZeroPool (sizeof (MMC_HOST_INSTANCE));\r
95 if (MmcHostInstance == NULL) {\r
96 return NULL;\r
97 }\r
1bfda055 98\r
e8e95df4 99 MmcHostInstance->Signature = MMC_HOST_INSTANCE_SIGNATURE;\r
1bfda055 100\r
e8e95df4 101 MmcHostInstance->State = MmcHwInitializationState;\r
1bfda055 102\r
e8e95df4 103 MmcHostInstance->BlockIo.Media = AllocateCopyPool (sizeof(EFI_BLOCK_IO_MEDIA), &mMmcMediaTemplate);\r
104 if (MmcHostInstance->BlockIo.Media == NULL) {\r
105 goto FREE_INSTANCE;\r
106 }\r
1bfda055 107\r
e8e95df4 108 MmcHostInstance->BlockIo.Revision = EFI_BLOCK_IO_INTERFACE_REVISION;\r
109 MmcHostInstance->BlockIo.Reset = MmcReset;\r
110 MmcHostInstance->BlockIo.ReadBlocks = MmcReadBlocks;\r
111 MmcHostInstance->BlockIo.WriteBlocks = MmcWriteBlocks;\r
112 MmcHostInstance->BlockIo.FlushBlocks = MmcFlushBlocks;\r
1bfda055 113\r
e8e95df4 114 MmcHostInstance->MmcHost = MmcHost;\r
115\r
116 // Create DevicePath for the new MMC Host\r
16d88c2d 117 Status = MmcHost->BuildDevicePath (MmcHost, &NewDevicePathNode);\r
e8e95df4 118 if (EFI_ERROR (Status)) {\r
119 goto FREE_MEDIA;\r
120 }\r
1bfda055 121\r
e8e95df4 122 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH);\r
123 if (DevicePath == NULL) {\r
124 goto FREE_MEDIA;\r
125 }\r
126\r
127 SetDevicePathEndNode (DevicePath);\r
128 MmcHostInstance->DevicePath = AppendDevicePathNode (DevicePath, NewDevicePathNode);\r
129\r
130 // Publish BlockIO protocol interface\r
131 Status = gBS->InstallMultipleProtocolInterfaces (\r
132 &MmcHostInstance->MmcHandle,\r
3de99375 133 &gEfiBlockIoProtocolGuid,&MmcHostInstance->BlockIo,\r
e8e95df4 134 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
135 NULL\r
136 );\r
137 if (EFI_ERROR(Status)) {\r
138 goto FREE_DEVICE_PATH;\r
139 }\r
140\r
141 return MmcHostInstance;\r
1bfda055 142\r
143FREE_DEVICE_PATH:\r
e8e95df4 144 FreePool(DevicePath);\r
1bfda055 145\r
146FREE_MEDIA:\r
e8e95df4 147 FreePool(MmcHostInstance->BlockIo.Media);\r
1bfda055 148\r
149FREE_INSTANCE:\r
e8e95df4 150 FreePool(MmcHostInstance);\r
1bfda055 151\r
e8e95df4 152 return NULL;\r
1bfda055 153}\r
154\r
e8e95df4 155EFI_STATUS DestroyMmcHostInstance (\r
1bfda055 156 IN MMC_HOST_INSTANCE* MmcHostInstance\r
157 )\r
158{\r
e8e95df4 159 EFI_STATUS Status;\r
1bfda055 160\r
e8e95df4 161 // Uninstall Protocol Interfaces\r
162 Status = gBS->UninstallMultipleProtocolInterfaces (\r
6102636a 163 MmcHostInstance->MmcHandle,\r
e8e95df4 164 &gEfiBlockIoProtocolGuid,&(MmcHostInstance->BlockIo),\r
6102636a 165 &gEfiDevicePathProtocolGuid,MmcHostInstance->DevicePath,\r
e8e95df4 166 NULL\r
167 );\r
168 ASSERT_EFI_ERROR (Status);\r
1bfda055 169\r
e8e95df4 170 // Free Memory allocated for the instance\r
171 if (MmcHostInstance->BlockIo.Media) {\r
172 FreePool(MmcHostInstance->BlockIo.Media);\r
173 }\r
174 FreePool (MmcHostInstance);\r
175\r
176 return Status;\r
1bfda055 177}\r
178\r
179/**\r
180 This function checks if the controller implement the Mmc Host and the Device Path Protocols\r
181**/\r
182EFI_STATUS\r
183EFIAPI\r
184MmcDriverBindingSupported (\r
185 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
186 IN EFI_HANDLE Controller,\r
187 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
188 )\r
189{\r
e8e95df4 190 EFI_STATUS Status;\r
191 //EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
192 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
193 EFI_DEV_PATH_PTR Node;\r
194\r
195 //\r
196 // Check RemainingDevicePath validation\r
197 //\r
198 if (RemainingDevicePath != NULL) {\r
1bfda055 199 //\r
e8e95df4 200 // Check if RemainingDevicePath is the End of Device Path Node,\r
201 // if yes, go on checking other conditions\r
1bfda055 202 //\r
e8e95df4 203 if (!IsDevicePathEnd (RemainingDevicePath)) {\r
204 //\r
205 // If RemainingDevicePath isn't the End of Device Path Node,\r
206 // check its validation\r
207 //\r
208 Node.DevPath = RemainingDevicePath;\r
209 if (Node.DevPath->Type != HARDWARE_DEVICE_PATH ||\r
210 Node.DevPath->SubType != HW_VENDOR_DP ||\r
211 DevicePathNodeLength(Node.DevPath) != sizeof(VENDOR_DEVICE_PATH)) {\r
212 return EFI_UNSUPPORTED;\r
213 }\r
1bfda055 214 }\r
e8e95df4 215 }\r
216\r
217 //\r
218 // Check if Mmc Host protocol is installed by platform\r
219 //\r
220 Status = gBS->OpenProtocol (\r
221 Controller,\r
222 &gEfiMmcHostProtocolGuid,\r
223 (VOID **) &MmcHost,\r
224 This->DriverBindingHandle,\r
225 Controller,\r
226 EFI_OPEN_PROTOCOL_BY_DRIVER\r
227 );\r
228 if (Status == EFI_ALREADY_STARTED) {\r
1bfda055 229 return EFI_SUCCESS;\r
e8e95df4 230 }\r
231 if (EFI_ERROR (Status)) {\r
232 return Status;\r
233 }\r
234\r
235 //\r
236 // Close the Mmc Host used to perform the supported test\r
237 //\r
238 gBS->CloseProtocol (\r
239 Controller,\r
240 &gEfiMmcHostProtocolGuid,\r
241 This->DriverBindingHandle,\r
242 Controller\r
243 );\r
244\r
245 return EFI_SUCCESS;\r
1bfda055 246}\r
247\r
248/**\r
249 \r
250**/\r
251EFI_STATUS\r
252EFIAPI\r
253MmcDriverBindingStart (\r
254 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
255 IN EFI_HANDLE Controller,\r
256 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
257 )\r
258{\r
e8e95df4 259 EFI_STATUS Status;\r
260 MMC_HOST_INSTANCE *MmcHostInstance;\r
261 EFI_MMC_HOST_PROTOCOL *MmcHost;\r
262\r
263 //\r
264 // Check RemainingDevicePath validation\r
265 //\r
266 if (RemainingDevicePath != NULL) {\r
1bfda055 267 //\r
e8e95df4 268 // Check if RemainingDevicePath is the End of Device Path Node,\r
269 // if yes, return EFI_SUCCESS\r
1bfda055 270 //\r
e8e95df4 271 if (IsDevicePathEnd (RemainingDevicePath)) {\r
272 return EFI_SUCCESS;\r
1bfda055 273 }\r
e8e95df4 274 }\r
275\r
276 //\r
277 // Get the Mmc Host protocol\r
278 //\r
279 Status = gBS->OpenProtocol (\r
280 Controller,\r
281 &gEfiMmcHostProtocolGuid,\r
282 (VOID **) &MmcHost,\r
283 This->DriverBindingHandle,\r
284 Controller,\r
285 EFI_OPEN_PROTOCOL_BY_DRIVER\r
286 );\r
287 if (EFI_ERROR (Status)) {\r
288 if (Status == EFI_ALREADY_STARTED) {\r
289 return EFI_SUCCESS;\r
1bfda055 290 }\r
e8e95df4 291 return Status;\r
292 }\r
1bfda055 293\r
e8e95df4 294 MmcHostInstance = CreateMmcHostInstance(MmcHost);\r
295 if (MmcHostInstance != NULL) {\r
296 // Add the handle to the pool\r
297 InsertMmcHost (MmcHostInstance);\r
3de99375 298\r
299 MmcHostInstance->Initialized = FALSE;\r
40842a5e 300\r
301 // Detect card presence now\r
302 CheckCardsCallback (NULL, NULL);\r
e8e95df4 303 }\r
1bfda055 304\r
e8e95df4 305 return EFI_SUCCESS;\r
1bfda055 306}\r
307\r
308/**\r
309 \r
310**/\r
311EFI_STATUS\r
312EFIAPI\r
313MmcDriverBindingStop (\r
314 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
315 IN EFI_HANDLE Controller,\r
316 IN UINTN NumberOfChildren,\r
317 IN EFI_HANDLE *ChildHandleBuffer\r
318 )\r
319{\r
e8e95df4 320 EFI_STATUS Status = EFI_SUCCESS;\r
321 LIST_ENTRY *CurrentLink;\r
322 MMC_HOST_INSTANCE *MmcHostInstance;\r
1bfda055 323\r
e8e95df4 324 MMC_TRACE("MmcDriverBindingStop()");\r
325\r
326 // For each MMC instance\r
327 CurrentLink = mMmcHostPool.ForwardLink;\r
328 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
329 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
330 ASSERT(MmcHostInstance != NULL);\r
331\r
332 // Close gEfiMmcHostProtocolGuid\r
333 Status = gBS->CloseProtocol (\r
334 Controller,\r
335 &gEfiMmcHostProtocolGuid,(VOID **) &MmcHostInstance->MmcHost,\r
336 This->DriverBindingHandle\r
337 );\r
338\r
339 // Remove MMC Host Instance from the pool\r
340 RemoveMmcHost (MmcHostInstance);\r
341\r
342 // Destroy MmcHostInstance\r
343 DestroyMmcHostInstance (MmcHostInstance);\r
344 }\r
345\r
346 return Status;\r
1bfda055 347}\r
348\r
3de99375 349VOID\r
350EFIAPI\r
351CheckCardsCallback (\r
352 IN EFI_EVENT Event,\r
353 IN VOID *Context\r
354 )\r
355{\r
356 LIST_ENTRY *CurrentLink;\r
357 MMC_HOST_INSTANCE *MmcHostInstance;\r
358 EFI_STATUS Status;\r
359\r
360 CurrentLink = mMmcHostPool.ForwardLink;\r
361 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool) {\r
362 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
363 ASSERT(MmcHostInstance != NULL);\r
364\r
16d88c2d 365 if (MmcHostInstance->MmcHost->IsCardPresent (MmcHostInstance->MmcHost) == !MmcHostInstance->Initialized) {\r
3de99375 366 MmcHostInstance->State = MmcHwInitializationState;\r
367 MmcHostInstance->BlockIo.Media->MediaPresent = !MmcHostInstance->Initialized;\r
368 MmcHostInstance->Initialized = !MmcHostInstance->Initialized;\r
369\r
16d88c2d 370 if (MmcHostInstance->BlockIo.Media->MediaPresent) {\r
371 InitializeMmcDevice (MmcHostInstance);\r
40842a5e 372 }\r
373\r
3de99375 374 Status = gBS->ReinstallProtocolInterface (\r
375 (MmcHostInstance->MmcHandle),\r
376 &gEfiBlockIoProtocolGuid,\r
377 &(MmcHostInstance->BlockIo),\r
378 &(MmcHostInstance->BlockIo)\r
379 );\r
380\r
381 if (EFI_ERROR(Status)) {\r
382 Print(L"MMC Card: Error reinstalling BlockIo interface\n");\r
383 }\r
384 }\r
385\r
386 CurrentLink = CurrentLink->ForwardLink;\r
387 }\r
388}\r
389\r
40842a5e 390\r
1bfda055 391EFI_DRIVER_BINDING_PROTOCOL gMmcDriverBinding = {\r
392 MmcDriverBindingSupported,\r
393 MmcDriverBindingStart,\r
394 MmcDriverBindingStop,\r
395 0xa,\r
396 NULL,\r
397 NULL\r
398};\r
399\r
400/**\r
401 \r
402**/\r
403EFI_STATUS\r
404EFIAPI\r
405MmcDxeInitialize (\r
406 IN EFI_HANDLE ImageHandle,\r
407 IN EFI_SYSTEM_TABLE *SystemTable\r
408 )\r
409{\r
e8e95df4 410 EFI_STATUS Status;\r
411\r
412 //\r
413 // Initializes MMC Host pool\r
414 //\r
415 InitializeMmcHostPool ();\r
416\r
417 //\r
418 // Install driver model protocol(s).\r
419 //\r
420 Status = EfiLibInstallDriverBindingComponentName2 (\r
421 ImageHandle,\r
422 SystemTable,\r
423 &gMmcDriverBinding,\r
424 ImageHandle,\r
425 &gMmcComponentName,\r
426 &gMmcComponentName2\r
427 );\r
428 ASSERT_EFI_ERROR (Status);\r
429\r
430 // Install driver diagnostics\r
431 Status = gBS->InstallMultipleProtocolInterfaces (\r
432 &ImageHandle,\r
433 &gEfiDriverDiagnostics2ProtocolGuid,&gMmcDriverDiagnostics2,\r
434 NULL\r
435 );\r
436 ASSERT_EFI_ERROR (Status);\r
437\r
3de99375 438 // Use a timer to detect if a card has been plugged in or removed\r
439 Status = gBS->CreateEvent (\r
440 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
441 TPL_CALLBACK,\r
442 CheckCardsCallback,\r
443 NULL,\r
444 &gCheckCardsEvent);\r
445 ASSERT_EFI_ERROR (Status); \r
446 \r
447 Status = gBS->SetTimer(\r
448 gCheckCardsEvent,\r
449 TimerPeriodic,\r
450 (UINT64)(10*1000*200)); // 200 ms\r
451 ASSERT_EFI_ERROR (Status);\r
452\r
e8e95df4 453 return Status;\r
1bfda055 454}\r