]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
Code scrubbing.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / ArpDxe / ArpDriver.c
1 /** @file
2 Abstract:
3
4 Copyright (c) 2006 - 2008, Intel Corporation.<BR>
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at<BR>
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "ArpDriver.h"
16 #include "ArpImpl.h"
17
18 EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {
19 ArpDriverBindingSupported,
20 ArpDriverBindingStart,
21 ArpDriverBindingStop,
22 0xa,
23 NULL,
24 NULL
25 };
26
27
28 /**
29 Create and initialize the arp service context data.
30
31 @param[in] ImageHandle The image handle representing the loaded driver
32 image.
33 @param[in] ControllerHandle The controller handle the driver binds to.
34 @param[in] ArpService Pointer to the buffer containing the arp service
35 context data.
36
37 @retval EFI_SUCCESS The arp service context is initialized.
38 @retval other Failed to initialize the arp service context.
39
40 **/
41 EFI_STATUS
42 ArpCreateService (
43 IN EFI_HANDLE ImageHandle,
44 IN EFI_HANDLE ControllerHandle,
45 IN ARP_SERVICE_DATA *ArpService
46 )
47 {
48 EFI_STATUS Status;
49
50 ASSERT (ArpService != NULL);
51
52 ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;
53
54 //
55 // Init the servicebinding protocol members.
56 //
57 ArpService->ServiceBinding.CreateChild = ArpServiceBindingCreateChild;
58 ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;
59
60 //
61 // Save the handles.
62 //
63 ArpService->ImageHandle = ImageHandle;
64 ArpService->ControllerHandle = ControllerHandle;
65
66 //
67 // Create a MNP child instance.
68 //
69 Status = NetLibCreateServiceChild (
70 ControllerHandle,
71 ImageHandle,
72 &gEfiManagedNetworkServiceBindingProtocolGuid,
73 &ArpService->MnpChildHandle
74 );
75 if (EFI_ERROR (Status)) {
76 return Status;
77 }
78
79 //
80 // Open the MNP protocol.
81 //
82 Status = gBS->OpenProtocol (
83 ArpService->MnpChildHandle,
84 &gEfiManagedNetworkProtocolGuid,
85 (VOID **)&ArpService->Mnp,
86 ImageHandle,
87 ControllerHandle,
88 EFI_OPEN_PROTOCOL_BY_DRIVER
89 );
90 if (EFI_ERROR (Status)) {
91 goto ERROR_EXIT;
92 }
93
94 //
95 // Get the underlayer Snp mode data.
96 //
97 Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
98 if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
99 goto ERROR_EXIT;
100 }
101
102 if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
103 //
104 // Only support the ethernet.
105 //
106 Status = EFI_UNSUPPORTED;
107 goto ERROR_EXIT;
108 }
109
110 //
111 // Set the Mnp config parameters.
112 //
113 ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
114 ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
115 ArpService->MnpConfigData.ProtocolTypeFilter = ARP_ETHER_PROTO_TYPE;
116 ArpService->MnpConfigData.EnableUnicastReceive = TRUE;
117 ArpService->MnpConfigData.EnableMulticastReceive = FALSE;
118 ArpService->MnpConfigData.EnableBroadcastReceive = TRUE;
119 ArpService->MnpConfigData.EnablePromiscuousReceive = FALSE;
120 ArpService->MnpConfigData.FlushQueuesOnReset = TRUE;
121 ArpService->MnpConfigData.EnableReceiveTimestamps = FALSE;
122 ArpService->MnpConfigData.DisableBackgroundPolling = FALSE;
123
124 //
125 // Configure the Mnp child.
126 //
127 Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
128 if (EFI_ERROR (Status)) {
129 goto ERROR_EXIT;
130 }
131
132 //
133 // Create the event used in the RxToken.
134 //
135 Status = gBS->CreateEvent (
136 EVT_NOTIFY_SIGNAL,
137 TPL_NOTIFY,
138 ArpOnFrameRcvd,
139 ArpService,
140 &ArpService->RxToken.Event
141 );
142 if (EFI_ERROR (Status)) {
143 goto ERROR_EXIT;
144 }
145
146 //
147 // Create the Arp heartbeat timer.
148 //
149 Status = gBS->CreateEvent (
150 EVT_NOTIFY_SIGNAL | EVT_TIMER,
151 TPL_CALLBACK,
152 ArpTimerHandler,
153 ArpService,
154 &ArpService->PeriodicTimer
155 );
156 if (EFI_ERROR (Status)) {
157 goto ERROR_EXIT;
158 }
159
160 //
161 // Start the heartbeat timer.
162 //
163 Status = gBS->SetTimer (
164 ArpService->PeriodicTimer,
165 TimerPeriodic,
166 ARP_PERIODIC_TIMER_INTERVAL
167 );
168 if (EFI_ERROR (Status)) {
169 goto ERROR_EXIT;
170 }
171
172 //
173 // Init the lists.
174 //
175 InitializeListHead (&ArpService->ChildrenList);
176 InitializeListHead (&ArpService->PendingRequestTable);
177 InitializeListHead (&ArpService->DeniedCacheTable);
178 InitializeListHead (&ArpService->ResolvedCacheTable);
179
180 ERROR_EXIT:
181
182 return Status;
183 }
184
185
186 /**
187 Clean the arp service context data.
188
189 @param[in] ArpService Pointer to the buffer containing the arp service
190 context data.
191
192 @return None.
193
194 **/
195 VOID
196 ArpCleanService (
197 IN ARP_SERVICE_DATA *ArpService
198 )
199 {
200 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
201
202 if (ArpService->PeriodicTimer != NULL) {
203 //
204 // Cancle and close the PeriodicTimer.
205 //
206 gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);
207 gBS->CloseEvent (ArpService->PeriodicTimer);
208 }
209
210 if (ArpService->RxToken.Event != NULL) {
211 //
212 // Cancle the RxToken and close the event in the RxToken.
213 //
214 ArpService->Mnp->Cancel (ArpService->Mnp, NULL);
215 gBS->CloseEvent (ArpService->RxToken.Event);
216 }
217
218 if (ArpService->Mnp != NULL) {
219 //
220 // Reset the Mnp child and close the Mnp protocol.
221 //
222 ArpService->Mnp->Configure (ArpService->Mnp, NULL);
223 gBS->CloseProtocol (
224 ArpService->MnpChildHandle,
225 &gEfiManagedNetworkProtocolGuid,
226 ArpService->ImageHandle,
227 ArpService->ControllerHandle
228 );
229 }
230
231 if (ArpService->MnpChildHandle != NULL) {
232 //
233 // Destroy the mnp child.
234 //
235 NetLibDestroyServiceChild(
236 ArpService->ControllerHandle,
237 ArpService->ImageHandle,
238 &gEfiManagedNetworkServiceBindingProtocolGuid,
239 ArpService->MnpChildHandle
240 );
241 }
242 }
243
244 /**
245 Test to see if this driver supports ControllerHandle.
246
247 This service is called by the EFI boot service ConnectController(). In
248 order to make drivers as small as possible, there are a few calling
249 restrictions for this service. ConnectController() must
250 follow these calling restrictions. If any other agent wishes to call
251 Supported() it must also follow these calling restrictions.
252
253 @param[in] This Protocol instance pointer.
254 @param[in] ControllerHandle Handle of device to test.
255 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
256 device to start.
257
258 @retval EFI_SUCCES This driver supports this device
259 @retval EFI_ALREADY_STARTED This driver is already running on this device.
260 @retval other This driver does not support this device.
261
262 **/
263 EFI_STATUS
264 EFIAPI
265 ArpDriverBindingSupported (
266 IN EFI_DRIVER_BINDING_PROTOCOL *This,
267 IN EFI_HANDLE ControllerHandle,
268 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
269 )
270 {
271 EFI_STATUS Status;
272
273 //
274 // Test to see if Arp SB is already installed.
275 //
276 Status = gBS->OpenProtocol (
277 ControllerHandle,
278 &gEfiArpServiceBindingProtocolGuid,
279 NULL,
280 This->DriverBindingHandle,
281 ControllerHandle,
282 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
283 );
284 if (Status == EFI_SUCCESS) {
285 return EFI_ALREADY_STARTED;
286 }
287
288 //
289 // Test to see if MNP SB is installed.
290 //
291 Status = gBS->OpenProtocol (
292 ControllerHandle,
293 &gEfiManagedNetworkServiceBindingProtocolGuid,
294 NULL,
295 This->DriverBindingHandle,
296 ControllerHandle,
297 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
298 );
299
300 return Status;
301 }
302
303
304 /**
305 Start this driver on ControllerHandle.
306
307 This service is called by the EFI boot service ConnectController(). In order to make
308 drivers as small as possible, there are a few calling restrictions for
309 this service. ConnectController() must follow these
310 calling restrictions. If any other agent wishes to call Start() it
311 must also follow these calling restrictions.
312
313 @param[in] This Protocol instance pointer.
314 @param[in] ControllerHandle Handle of device to bind driver to.
315 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
316 device to start.
317
318 @retval EFI_SUCCES This driver is added to ControllerHandle.
319 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
320 @retval other This driver does not support this device.
321
322 **/
323 EFI_STATUS
324 EFIAPI
325 ArpDriverBindingStart (
326 IN EFI_DRIVER_BINDING_PROTOCOL *This,
327 IN EFI_HANDLE ControllerHandle,
328 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
329 )
330 {
331 EFI_STATUS Status;
332 ARP_SERVICE_DATA *ArpService;
333
334 //
335 // Allocate a zero pool for ArpService.
336 //
337 ArpService = AllocateZeroPool (sizeof(ARP_SERVICE_DATA));
338 if (ArpService == NULL) {
339 return EFI_OUT_OF_RESOURCES;
340 }
341
342 //
343 // Initialize the arp service context data.
344 //
345 Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);
346 if (EFI_ERROR (Status)) {
347 goto ERROR;
348 }
349
350 //
351 // Install the ARP service binding protocol.
352 //
353 Status = gBS->InstallMultipleProtocolInterfaces (
354 &ControllerHandle,
355 &gEfiArpServiceBindingProtocolGuid,
356 &ArpService->ServiceBinding,
357 NULL
358 );
359 if (EFI_ERROR (Status)) {
360 goto ERROR;
361 }
362
363 //
364 // OK, start to receive arp packets from Mnp.
365 //
366 Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);
367 if (EFI_ERROR (Status)) {
368 goto ERROR;
369 }
370
371 return Status;
372
373 ERROR:
374
375 //
376 // On error, clean the arp service context data, and free the memory allocated.
377 //
378 ArpCleanService (ArpService);
379 gBS->FreePool (ArpService);
380
381 return Status;
382 }
383
384
385 /**
386 Stop this driver on ControllerHandle.
387
388 This service is called by the EFI boot service DisconnectController(). In order to
389 make drivers as small as possible, there are a few calling
390 restrictions for this service. DisconnectController()
391 must follow these calling restrictions. If any other agent wishes
392 to call Stop() it must also follow these calling restrictions.
393
394 @param[in] This Protocol instance pointer.
395 @param[in] ControllerHandle Handle of device to stop driver on
396 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
397 of children is zero stop the entire bus driver.
398 @param[in] ChildHandleBuffer List of Child Handles to Stop.
399
400 @retval EFI_SUCCES This driver is removed ControllerHandle
401 @retval other This driver was not removed from this device
402
403 **/
404 EFI_STATUS
405 EFIAPI
406 ArpDriverBindingStop (
407 IN EFI_DRIVER_BINDING_PROTOCOL *This,
408 IN EFI_HANDLE ControllerHandle,
409 IN UINTN NumberOfChildren,
410 IN EFI_HANDLE *ChildHandleBuffer
411 )
412 {
413 EFI_STATUS Status;
414 EFI_HANDLE NicHandle;
415 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
416 ARP_SERVICE_DATA *ArpService;
417 ARP_INSTANCE_DATA *Instance;
418
419 //
420 // Get the NicHandle which the arp servicebinding is installed on.
421 //
422 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
423 if (NicHandle == NULL) {
424 return EFI_DEVICE_ERROR;
425 }
426
427 //
428 // Try to get the arp servicebinding protocol on the NicHandle.
429 //
430 Status = gBS->OpenProtocol (
431 NicHandle,
432 &gEfiArpServiceBindingProtocolGuid,
433 (VOID **)&ServiceBinding,
434 This->DriverBindingHandle,
435 ControllerHandle,
436 EFI_OPEN_PROTOCOL_GET_PROTOCOL
437 );
438 if (EFI_ERROR (Status)) {
439 DEBUG ((EFI_D_ERROR, "ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));
440 return EFI_DEVICE_ERROR;
441 }
442
443 ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);
444
445 if (NumberOfChildren == 0) {
446 //
447 // Uninstall the ARP ServiceBinding protocol.
448 //
449 gBS->UninstallMultipleProtocolInterfaces (
450 NicHandle,
451 &gEfiArpServiceBindingProtocolGuid,
452 &ArpService->ServiceBinding,
453 NULL
454 );
455
456 //
457 // Clean the arp servicebinding context data and free the memory allocated.
458 //
459 ArpCleanService (ArpService);
460
461 gBS->FreePool (ArpService);
462 } else {
463
464 while (!IsListEmpty (&ArpService->ChildrenList)) {
465 Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);
466
467 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
468 }
469
470 ASSERT (IsListEmpty (&ArpService->PendingRequestTable));
471 ASSERT (IsListEmpty (&ArpService->DeniedCacheTable));
472 ASSERT (IsListEmpty (&ArpService->ResolvedCacheTable));
473 }
474
475 return EFI_SUCCESS;
476 }
477
478 /**
479 Creates a child handle with a set of I/O services.
480
481 @param[in] This Protocol instance pointer.
482 @param[in] ChildHandle Pointer to the handle of the child to create. If
483 it is NULL, then a new handle is created. If it is
484 not NULL, then the I/O services are added to the
485 existing child handle.
486
487 @retval EFI_SUCCES The child handle was created with the I/O
488 services.
489 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
490 the child.
491 @retval other The child handle was not created.
492
493 **/
494 EFI_STATUS
495 EFIAPI
496 ArpServiceBindingCreateChild (
497 IN EFI_SERVICE_BINDING_PROTOCOL *This,
498 IN EFI_HANDLE *ChildHandle
499 )
500 {
501 EFI_STATUS Status;
502 ARP_SERVICE_DATA *ArpService;
503 ARP_INSTANCE_DATA *Instance;
504 VOID *Mnp;
505 EFI_TPL OldTpl;
506
507 if ((This == NULL) || (ChildHandle == NULL)) {
508 return EFI_INVALID_PARAMETER;
509 }
510
511 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
512
513 //
514 // Allocate memory for the instance context data.
515 //
516 Instance = AllocateZeroPool (sizeof(ARP_INSTANCE_DATA));
517 if (Instance == NULL) {
518 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: Failed to allocate memory for Instance.\n"));
519
520 return EFI_OUT_OF_RESOURCES;
521 }
522
523 //
524 // Init the instance context data.
525 //
526 ArpInitInstance (ArpService, Instance);
527
528 //
529 // Install the ARP protocol onto the ChildHandle.
530 //
531 Status = gBS->InstallMultipleProtocolInterfaces (
532 ChildHandle,
533 &gEfiArpProtocolGuid,
534 (VOID *)&Instance->ArpProto,
535 NULL
536 );
537 if (EFI_ERROR (Status)) {
538 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));
539
540 gBS->FreePool (Instance);
541 return Status;
542 }
543
544 //
545 // Save the ChildHandle.
546 //
547 Instance->Handle = *ChildHandle;
548
549 //
550 // Open the Managed Network protocol BY_CHILD.
551 //
552 Status = gBS->OpenProtocol (
553 ArpService->MnpChildHandle,
554 &gEfiManagedNetworkProtocolGuid,
555 (VOID **) &Mnp,
556 gArpDriverBinding.DriverBindingHandle,
557 Instance->Handle,
558 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
559 );
560 if (EFI_ERROR (Status)) {
561 goto ERROR;
562 }
563
564 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
565
566 //
567 // Insert the instance into children list managed by the arp service context data.
568 //
569 InsertTailList (&ArpService->ChildrenList, &Instance->List);
570 ArpService->ChildrenNumber++;
571
572 gBS->RestoreTPL (OldTpl);
573
574 ERROR:
575
576 if (EFI_ERROR (Status)) {
577
578 gBS->CloseProtocol (
579 ArpService->MnpChildHandle,
580 &gEfiManagedNetworkProtocolGuid,
581 gArpDriverBinding.DriverBindingHandle,
582 Instance->Handle
583 );
584
585 gBS->UninstallMultipleProtocolInterfaces (
586 Instance->Handle,
587 &gEfiArpProtocolGuid,
588 &Instance->ArpProto,
589 NULL
590 );
591
592 //
593 // Free the allocated memory.
594 //
595 gBS->FreePool (Instance);
596 }
597
598 return Status;
599 }
600
601
602 /**
603 Destroys a child handle with a set of I/O services.
604
605 @param[in] This Protocol instance pointer.
606 @param[in] ChildHandle Handle of the child to destroy.
607
608 @retval EFI_SUCCES The I/O services were removed from the child
609 handle.
610 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
611 that are being removed.
612 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
613 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
614 its I/O services are being used.
615 @retval other The child handle was not destroyed.
616
617 **/
618 EFI_STATUS
619 EFIAPI
620 ArpServiceBindingDestroyChild (
621 IN EFI_SERVICE_BINDING_PROTOCOL *This,
622 IN EFI_HANDLE ChildHandle
623 )
624 {
625 EFI_STATUS Status;
626 ARP_SERVICE_DATA *ArpService;
627 ARP_INSTANCE_DATA *Instance;
628 EFI_ARP_PROTOCOL *Arp;
629 EFI_TPL OldTpl;
630
631 if ((This == NULL) || (ChildHandle == NULL)) {
632 return EFI_INVALID_PARAMETER;
633 }
634
635 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
636
637 //
638 // Get the arp protocol.
639 //
640 Status = gBS->OpenProtocol (
641 ChildHandle,
642 &gEfiArpProtocolGuid,
643 (VOID **)&Arp,
644 ArpService->ImageHandle,
645 ChildHandle,
646 EFI_OPEN_PROTOCOL_GET_PROTOCOL
647 );
648 if (EFI_ERROR (Status)) {
649 return EFI_UNSUPPORTED;
650 }
651
652 Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);
653
654 if (Instance->Destroyed) {
655 return EFI_SUCCESS;
656 }
657
658 //
659 // Use the Destroyed as a flag to avoid re-entrance.
660 //
661 Instance->Destroyed = TRUE;
662
663 //
664 // Close the Managed Network protocol.
665 //
666 gBS->CloseProtocol (
667 ArpService->MnpChildHandle,
668 &gEfiManagedNetworkProtocolGuid,
669 gArpDriverBinding.DriverBindingHandle,
670 ChildHandle
671 );
672
673 //
674 // Uninstall the ARP protocol.
675 //
676 Status = gBS->UninstallMultipleProtocolInterfaces (
677 ChildHandle,
678 &gEfiArpProtocolGuid,
679 &Instance->ArpProto,
680 NULL
681 );
682 if (EFI_ERROR (Status)) {
683 DEBUG ((EFI_D_ERROR, "ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",
684 Status));
685
686 Instance->Destroyed = FALSE;
687 return Status;
688 }
689
690 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
691
692 if (Instance->Configured) {
693 //
694 // Delete the related cache entry.
695 //
696 ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);
697
698 //
699 // Reset the instance configuration.
700 //
701 ArpConfigureInstance (Instance, NULL);
702 }
703
704 //
705 // Remove this instance from the ChildrenList.
706 //
707 RemoveEntryList (&Instance->List);
708 ArpService->ChildrenNumber--;
709
710 gBS->RestoreTPL (OldTpl);
711
712 gBS->FreePool (Instance);
713
714 return Status;
715 }
716
717 /**
718 The entry point for Arp driver which installs the driver binding and component name
719 protocol on its ImageHandle.
720
721 @param[in] ImageHandle The image handle of the driver.
722 @param[in] SystemTable The system table.
723
724 @retval EFI_SUCCES if the driver binding and component name protocols are successfully
725 @retval Others Failed to install the protocols.
726
727 **/
728 EFI_STATUS
729 EFIAPI
730 ArpDriverEntryPoint (
731 IN EFI_HANDLE ImageHandle,
732 IN EFI_SYSTEM_TABLE *SystemTable
733 )
734 {
735 return EfiLibInstallDriverBindingComponentName2 (
736 ImageHandle,
737 SystemTable,
738 &gArpDriverBinding,
739 ImageHandle,
740 &gArpComponentName,
741 &gArpComponentName2
742 );
743 }
744