]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/MnpDxe/MnpDriver.c
In Supported(), try to test open SNP protocol BY_DRIVER instead of using TEST_PROTOCOL.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / MnpDxe / MnpDriver.c
1 /** @file
2
3 Copyright (c) 2005 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 MnpDriver.c
15
16 Abstract:
17
18
19 **/
20
21 #include "MnpDriver.h"
22 #include "MnpImpl.h"
23
24
25 EFI_DRIVER_BINDING_PROTOCOL gMnpDriverBinding = {
26 MnpDriverBindingSupported,
27 MnpDriverBindingStart,
28 MnpDriverBindingStop,
29 0xa,
30 NULL,
31 NULL
32 };
33
34
35 /**
36 Test to see if this driver supports ControllerHandle.
37
38 @param This Protocol instance pointer.
39 @param ControllerHandle Handle of device to test.
40 @param RemainingDevicePath Optional parameter use to pick a specific child
41 device to start.
42
43 @retval EFI_SUCCES This driver supports this device.
44 @retval EFI_ALREADY_STARTED This driver is already running on this device.
45 @retval other This driver does not support this device.
46
47 **/
48 EFI_STATUS
49 EFIAPI
50 MnpDriverBindingSupported (
51 IN EFI_DRIVER_BINDING_PROTOCOL *This,
52 IN EFI_HANDLE ControllerHandle,
53 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
54 )
55 {
56 EFI_STATUS Status;
57 EFI_SIMPLE_NETWORK_PROTOCOL *Snp;
58
59 //
60 // Test to see if MNP is already installed.
61 //
62 Status = gBS->OpenProtocol (
63 ControllerHandle,
64 &gEfiManagedNetworkServiceBindingProtocolGuid,
65 NULL,
66 This->DriverBindingHandle,
67 ControllerHandle,
68 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
69 );
70 if (!EFI_ERROR (Status)) {
71 return EFI_ALREADY_STARTED;
72 }
73
74 //
75 // Test to open the Simple Network protocol BY_DRIVER.
76 //
77 Status = gBS->OpenProtocol (
78 ControllerHandle,
79 &gEfiSimpleNetworkProtocolGuid,
80 (VOID **) &Snp,
81 This->DriverBindingHandle,
82 ControllerHandle,
83 EFI_OPEN_PROTOCOL_BY_DRIVER
84 );
85
86 if (EFI_ERROR (Status)) {
87 return Status;
88 }
89
90 //
91 // Close the openned SNP protocol.
92 //
93 gBS->CloseProtocol (
94 ControllerHandle,
95 &gEfiSimpleNetworkProtocolGuid,
96 This->DriverBindingHandle,
97 ControllerHandle
98 );
99
100 return EFI_SUCCESS;
101 }
102
103
104 /**
105 Start this driver on ControllerHandle.
106
107 @param This Protocol instance pointer.
108 @param ControllerHandle Handle of device to bind driver to.
109 @param RemainingDevicePath Optional parameter use to pick a specific child
110 device to start.
111
112 @retval EFI_SUCCES This driver is added to ControllerHandle.
113 @retval EFI_ALREADY_STARTED This driver is already running on
114 ControllerHandle.
115 @retval other This driver does not support this device.
116
117 **/
118 EFI_STATUS
119 EFIAPI
120 MnpDriverBindingStart (
121 IN EFI_DRIVER_BINDING_PROTOCOL *This,
122 IN EFI_HANDLE ControllerHandle,
123 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
124 )
125 {
126 EFI_STATUS Status;
127 MNP_SERVICE_DATA *MnpServiceData;
128 BOOLEAN MnpInitialized;
129
130 MnpInitialized = FALSE;
131
132 MnpServiceData = AllocateZeroPool (sizeof (MNP_SERVICE_DATA));
133 if (MnpServiceData == NULL) {
134 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart(): Failed to allocate the Mnp Service Data.\n"));
135
136 return EFI_OUT_OF_RESOURCES;
137 }
138
139 //
140 // Initialize the Mnp Service Data.
141 //
142 Status = MnpInitializeServiceData (MnpServiceData, This->DriverBindingHandle, ControllerHandle);
143 if (EFI_ERROR (Status)) {
144
145 DEBUG ((EFI_D_ERROR, "MnpDriverBindingStart: MnpInitializeServiceData failed, %r.\n",Status));
146 goto ErrorExit;
147 }
148
149 MnpInitialized = TRUE;
150
151 //
152 // Install the MNP Service Binding Protocol.
153 //
154 Status = gBS->InstallMultipleProtocolInterfaces (
155 &ControllerHandle,
156 &gEfiManagedNetworkServiceBindingProtocolGuid,
157 &MnpServiceData->ServiceBinding,
158 NULL
159 );
160
161 ErrorExit:
162
163 if (EFI_ERROR (Status)) {
164
165 if (MnpInitialized) {
166 //
167 // Flush the Mnp Service Data.
168 //
169 MnpFlushServiceData (MnpServiceData);
170 }
171
172 //
173 // Close the Simple Network Protocol.
174 //
175 gBS->CloseProtocol (
176 ControllerHandle,
177 &gEfiSimpleNetworkProtocolGuid,
178 This->DriverBindingHandle,
179 ControllerHandle
180 );
181
182 gBS->FreePool (MnpServiceData);
183 }
184
185 return Status;
186 }
187
188
189 /**
190 Stop this driver on ControllerHandle.
191
192 @param This Protocol instance pointer.
193 @param ControllerHandle Handle of device to stop driver on.
194 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
195 of children is zero stop the entire bus driver.
196 @param ChildHandleBuffer List of Child Handles to Stop.
197
198 @retval EFI_SUCCES This driver is removed ControllerHandle.
199 @retval other This driver was not removed from this device.
200
201 **/
202 EFI_STATUS
203 EFIAPI
204 MnpDriverBindingStop (
205 IN EFI_DRIVER_BINDING_PROTOCOL *This,
206 IN EFI_HANDLE ControllerHandle,
207 IN UINTN NumberOfChildren,
208 IN EFI_HANDLE *ChildHandleBuffer
209 )
210 {
211 EFI_STATUS Status;
212 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
213 MNP_SERVICE_DATA *MnpServiceData;
214 MNP_INSTANCE_DATA *Instance;
215
216 //
217 // Retrieve the MNP service binding protocol from the ControllerHandle.
218 //
219 Status = gBS->OpenProtocol (
220 ControllerHandle,
221 &gEfiManagedNetworkServiceBindingProtocolGuid,
222 (VOID **) &ServiceBinding,
223 This->DriverBindingHandle,
224 ControllerHandle,
225 EFI_OPEN_PROTOCOL_GET_PROTOCOL
226 );
227 if (EFI_ERROR (Status)) {
228
229 DEBUG (
230 (EFI_D_ERROR,
231 "MnpDriverBindingStop: Locate MNP Service Binding Protocol failed, %r.\n",
232 Status)
233 );
234 return EFI_DEVICE_ERROR;
235 }
236
237 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (ServiceBinding);
238
239 if (NumberOfChildren == 0) {
240 //
241 // Uninstall the MNP Service Binding Protocol.
242 //
243 gBS->UninstallMultipleProtocolInterfaces (
244 ControllerHandle,
245 &gEfiManagedNetworkServiceBindingProtocolGuid,
246 ServiceBinding,
247 NULL
248 );
249
250 //
251 // Close the openned Snp protocol.
252 //
253 gBS->CloseProtocol (
254 ControllerHandle,
255 &gEfiSimpleNetworkProtocolGuid,
256 This->DriverBindingHandle,
257 ControllerHandle
258 );
259
260 //
261 // Flush the Mnp service data.
262 //
263 MnpFlushServiceData (MnpServiceData);
264
265 gBS->FreePool (MnpServiceData);
266 } else {
267 while (!IsListEmpty (&MnpServiceData->ChildrenList)) {
268 //
269 // Don't use NetListRemoveHead here, the remove opreration will be done
270 // in ServiceBindingDestroyChild.
271 //
272 Instance = NET_LIST_HEAD (
273 &MnpServiceData->ChildrenList,
274 MNP_INSTANCE_DATA,
275 InstEntry
276 );
277
278 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
279 }
280 }
281
282 return Status;
283 }
284
285
286 /**
287 Creates a child handle with a set of I/O services.
288
289 @param This Protocol instance pointer.
290 @param ChildHandle Pointer to the handle of the child to create. If
291 it is NULL, then a new handle is created. If it is
292 not NULL, then the I/O services are added to the
293 existing child handle.
294
295 @retval EFI_SUCCES The child handle was created with the I/O
296 services.
297 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
298 the child.
299 @retval other The child handle was not created.
300
301 **/
302 EFI_STATUS
303 EFIAPI
304 MnpServiceBindingCreateChild (
305 IN EFI_SERVICE_BINDING_PROTOCOL *This,
306 IN EFI_HANDLE *ChildHandle
307 )
308 {
309 EFI_STATUS Status;
310 MNP_SERVICE_DATA *MnpServiceData;
311 MNP_INSTANCE_DATA *Instance;
312 VOID *Snp;
313 EFI_TPL OldTpl;
314
315 if ((This == NULL) || (ChildHandle == NULL)) {
316
317 return EFI_INVALID_PARAMETER;
318 }
319
320 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
321
322 //
323 // Allocate buffer for the new instance.
324 //
325 Instance = AllocateZeroPool (sizeof (MNP_INSTANCE_DATA));
326 if (Instance == NULL) {
327
328 DEBUG ((EFI_D_ERROR, "MnpServiceBindingCreateChild: Faild to allocate memory for the new instance.\n"));
329 return EFI_OUT_OF_RESOURCES;
330 }
331
332 //
333 // Init the instance data.
334 //
335 MnpInitializeInstanceData (MnpServiceData, Instance);
336
337 Status = gBS->InstallMultipleProtocolInterfaces (
338 ChildHandle,
339 &gEfiManagedNetworkProtocolGuid,
340 &Instance->ManagedNetwork,
341 NULL
342 );
343 if (EFI_ERROR (Status)) {
344
345 DEBUG (
346 (EFI_D_ERROR,
347 "MnpServiceBindingCreateChild: Failed to install the MNP protocol, %r.\n",
348 Status)
349 );
350 goto ErrorExit;
351 }
352
353 //
354 // Save the instance's childhandle.
355 //
356 Instance->Handle = *ChildHandle;
357
358 Status = gBS->OpenProtocol (
359 MnpServiceData->ControllerHandle,
360 &gEfiSimpleNetworkProtocolGuid,
361 (VOID **) &Snp,
362 gMnpDriverBinding.DriverBindingHandle,
363 Instance->Handle,
364 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
365 );
366 if (EFI_ERROR (Status)) {
367 goto ErrorExit;
368 }
369
370 //
371 // Add the child instance into ChildrenList.
372 //
373 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
374
375 InsertTailList (&MnpServiceData->ChildrenList, &Instance->InstEntry);
376 MnpServiceData->ChildrenNumber++;
377
378 gBS->RestoreTPL (OldTpl);
379
380 ErrorExit:
381
382 if (EFI_ERROR (Status)) {
383
384 if (Instance->Handle != NULL) {
385
386 gBS->UninstallMultipleProtocolInterfaces (
387 &gEfiManagedNetworkProtocolGuid,
388 &Instance->ManagedNetwork,
389 NULL
390 );
391 }
392
393 gBS->FreePool (Instance);
394 }
395
396 return Status;
397 }
398
399
400 /**
401 Destroys a child handle with a set of I/O services.
402
403 @param This Protocol instance pointer.
404 @param ChildHandle Handle of the child to destroy.
405
406 @retval EFI_SUCCES The I/O services were removed from the child
407 handle.
408 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
409 that are being removed.
410 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
411 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
412 its I/O services are being used.
413 @retval other The child handle was not destroyed.
414
415 **/
416 EFI_STATUS
417 EFIAPI
418 MnpServiceBindingDestroyChild (
419 IN EFI_SERVICE_BINDING_PROTOCOL *This,
420 IN EFI_HANDLE ChildHandle
421 )
422 {
423 EFI_STATUS Status;
424 MNP_SERVICE_DATA *MnpServiceData;
425 EFI_MANAGED_NETWORK_PROTOCOL *ManagedNetwork;
426 MNP_INSTANCE_DATA *Instance;
427 EFI_TPL OldTpl;
428
429 if ((This == NULL) || (ChildHandle == NULL)) {
430
431 return EFI_INVALID_PARAMETER;
432 }
433
434 MnpServiceData = MNP_SERVICE_DATA_FROM_THIS (This);
435
436 //
437 // Try to retrieve ManagedNetwork Protocol from ChildHandle.
438 //
439 Status = gBS->OpenProtocol (
440 ChildHandle,
441 &gEfiManagedNetworkProtocolGuid,
442 (VOID **) &ManagedNetwork,
443 gMnpDriverBinding.DriverBindingHandle,
444 ChildHandle,
445 EFI_OPEN_PROTOCOL_GET_PROTOCOL
446 );
447 if (EFI_ERROR (Status)) {
448
449 return EFI_UNSUPPORTED;
450 }
451
452 Instance = MNP_INSTANCE_DATA_FROM_THIS (ManagedNetwork);
453
454 //
455 // MnpServiceBindingDestroyChild may be called twice: first called by
456 // MnpServiceBindingStop, second called by uninstalling the MNP protocol
457 // in this ChildHandle. Use destroyed to make sure the resource clean code
458 // will only excecute once.
459 //
460 if (Instance->Destroyed) {
461
462 return EFI_SUCCESS;
463 }
464
465 Instance->Destroyed = TRUE;
466
467 //
468 // Close the Simple Network protocol.
469 //
470 gBS->CloseProtocol (
471 MnpServiceData->ControllerHandle,
472 &gEfiSimpleNetworkProtocolGuid,
473 gMnpDriverBinding.DriverBindingHandle,
474 ChildHandle
475 );
476
477 //
478 // Uninstall the ManagedNetwork protocol.
479 //
480 Status = gBS->UninstallMultipleProtocolInterfaces (
481 ChildHandle,
482 &gEfiManagedNetworkProtocolGuid,
483 &Instance->ManagedNetwork,
484 NULL
485 );
486 if (EFI_ERROR (Status)) {
487
488 DEBUG (
489 (EFI_D_ERROR,
490 "MnpServiceBindingDestroyChild: Failed to uninstall the ManagedNetwork protocol, %r.\n",
491 Status)
492 );
493
494 Instance->Destroyed = FALSE;
495 return Status;
496 }
497
498 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
499
500 //
501 // Reset the configuration.
502 //
503 ManagedNetwork->Configure (ManagedNetwork, NULL);
504
505 //
506 // Try to flush the RcvdPacketQueue.
507 //
508 MnpFlushRcvdDataQueue (Instance);
509
510 //
511 // Clean the RxTokenMap.
512 //
513 NetMapClean (&Instance->RxTokenMap);
514
515 //
516 // Remove this instance from the ChildrenList.
517 //
518 RemoveEntryList (&Instance->InstEntry);
519 MnpServiceData->ChildrenNumber--;
520
521 gBS->RestoreTPL (OldTpl);
522
523 gBS->FreePool (Instance);
524
525 return Status;
526 }
527
528
529 EFI_STATUS
530 EFIAPI
531 MnpDriverEntryPoint (
532 IN EFI_HANDLE ImageHandle,
533 IN EFI_SYSTEM_TABLE *SystemTable
534 )
535 /*++
536
537 Routine Description:
538
539 The entry point for Mnp driver which installs the driver binding and component name
540 protocol on its ImageHandle.
541
542 Arguments:
543
544 ImageHandle - The image handle of the driver.
545 SystemTable - The system table.
546
547 Returns:
548
549 EFI_SUCCESS - If the driver binding and component name protocols are successfully
550 installed, otherwise if failed.
551
552 --*/
553 {
554 return EfiLibInstallDriverBindingComponentName2 (
555 ImageHandle,
556 SystemTable,
557 &gMnpDriverBinding,
558 ImageHandle,
559 &gMnpComponentName,
560 &gMnpComponentName2
561 );
562 }