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