3 Copyright (c) 2006 - 2008, Intel Corporation
\r
4 All rights reserved. This program and the accompanying materials
\r
5 are licensed and made available under the terms and conditions of the BSD License
\r
6 which accompanies this distribution. The full text of the license may be found at
\r
7 http://opensource.org/licenses/bsd-license.php
\r
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
22 #include "ArpDriver.h"
\r
23 #include "ArpImpl.h"
\r
25 EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {
\r
26 ArpDriverBindingSupported,
\r
27 ArpDriverBindingStart,
\r
28 ArpDriverBindingStop,
\r
36 Create and initialize the arp service context data.
\r
38 @param ImageHandle The image handle representing the loaded driver
\r
40 @param ControllerHandle The controller handle the driver binds to.
\r
41 @param ArpService Pointer to the buffer containing the arp service
\r
44 @retval EFI_SUCCESS The arp service context is initialized.
\r
45 @retval other Failed to initialize the arp service context.
\r
50 IN EFI_HANDLE ImageHandle,
\r
51 IN EFI_HANDLE ControllerHandle,
\r
52 IN ARP_SERVICE_DATA *ArpService
\r
57 ASSERT (ArpService != NULL);
\r
59 ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;
\r
62 // Init the servicebinding protocol members.
\r
64 ArpService->ServiceBinding.CreateChild = ArpServiceBindingCreateChild;
\r
65 ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;
\r
68 // Save the handles.
\r
70 ArpService->ImageHandle = ImageHandle;
\r
71 ArpService->ControllerHandle = ControllerHandle;
\r
74 // Create a MNP child instance.
\r
76 Status = NetLibCreateServiceChild (
\r
79 &gEfiManagedNetworkServiceBindingProtocolGuid,
\r
80 &ArpService->MnpChildHandle
\r
82 if (EFI_ERROR (Status)) {
\r
87 // Open the MNP protocol.
\r
89 Status = gBS->OpenProtocol (
\r
90 ArpService->MnpChildHandle,
\r
91 &gEfiManagedNetworkProtocolGuid,
\r
92 (VOID **)&ArpService->Mnp,
\r
95 EFI_OPEN_PROTOCOL_BY_DRIVER
\r
97 if (EFI_ERROR (Status)) {
\r
102 // Get the underlayer Snp mode data.
\r
104 Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
\r
105 if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
\r
109 if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
\r
111 // Only support the ethernet.
\r
113 Status = EFI_UNSUPPORTED;
\r
118 // Set the Mnp config parameters.
\r
120 ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
\r
121 ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
\r
122 ArpService->MnpConfigData.ProtocolTypeFilter = ARP_ETHER_PROTO_TYPE;
\r
123 ArpService->MnpConfigData.EnableUnicastReceive = TRUE;
\r
124 ArpService->MnpConfigData.EnableMulticastReceive = FALSE;
\r
125 ArpService->MnpConfigData.EnableBroadcastReceive = TRUE;
\r
126 ArpService->MnpConfigData.EnablePromiscuousReceive = FALSE;
\r
127 ArpService->MnpConfigData.FlushQueuesOnReset = TRUE;
\r
128 ArpService->MnpConfigData.EnableReceiveTimestamps = FALSE;
\r
129 ArpService->MnpConfigData.DisableBackgroundPolling = FALSE;
\r
132 // Configure the Mnp child.
\r
134 Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
\r
135 if (EFI_ERROR (Status)) {
\r
140 // Create the event used in the RxToken.
\r
142 Status = gBS->CreateEvent (
\r
147 &ArpService->RxToken.Event
\r
149 if (EFI_ERROR (Status)) {
\r
154 // Create the Arp heartbeat timer.
\r
156 Status = gBS->CreateEvent (
\r
157 EVT_NOTIFY_SIGNAL | EVT_TIMER,
\r
161 &ArpService->PeriodicTimer
\r
163 if (EFI_ERROR (Status)) {
\r
168 // Start the heartbeat timer.
\r
170 Status = gBS->SetTimer (
\r
171 ArpService->PeriodicTimer,
\r
173 ARP_PERIODIC_TIMER_INTERVAL
\r
175 if (EFI_ERROR (Status)) {
\r
182 InitializeListHead (&ArpService->ChildrenList);
\r
183 InitializeListHead (&ArpService->PendingRequestTable);
\r
184 InitializeListHead (&ArpService->DeniedCacheTable);
\r
185 InitializeListHead (&ArpService->ResolvedCacheTable);
\r
194 Clean the arp service context data.
\r
196 @param ArpService Pointer to the buffer containing the arp service
\r
204 IN ARP_SERVICE_DATA *ArpService
\r
207 NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
\r
209 if (ArpService->PeriodicTimer != NULL) {
\r
211 // Cancle and close the PeriodicTimer.
\r
213 gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);
\r
214 gBS->CloseEvent (ArpService->PeriodicTimer);
\r
217 if (ArpService->RxToken.Event != NULL) {
\r
219 // Cancle the RxToken and close the event in the RxToken.
\r
221 ArpService->Mnp->Cancel (ArpService->Mnp, NULL);
\r
222 gBS->CloseEvent (ArpService->RxToken.Event);
\r
225 if (ArpService->Mnp != NULL) {
\r
227 // Reset the Mnp child and close the Mnp protocol.
\r
229 ArpService->Mnp->Configure (ArpService->Mnp, NULL);
\r
230 gBS->CloseProtocol (
\r
231 ArpService->MnpChildHandle,
\r
232 &gEfiManagedNetworkProtocolGuid,
\r
233 ArpService->ImageHandle,
\r
234 ArpService->ControllerHandle
\r
238 if (ArpService->MnpChildHandle != NULL) {
\r
240 // Destroy the mnp child.
\r
242 NetLibDestroyServiceChild(
\r
243 ArpService->ControllerHandle,
\r
244 ArpService->ImageHandle,
\r
245 &gEfiManagedNetworkServiceBindingProtocolGuid,
\r
246 ArpService->MnpChildHandle
\r
253 Test to see if this driver supports ControllerHandle.
\r
255 @param This Protocol instance pointer.
\r
256 @param ControllerHandle Handle of device to test.
\r
257 @param RemainingDevicePath Optional parameter use to pick a specific child
\r
260 @retval EFI_SUCCES This driver supports this device
\r
261 @retval EFI_ALREADY_STARTED This driver is already running on this device.
\r
262 @retval other This driver does not support this device.
\r
267 ArpDriverBindingSupported (
\r
268 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
269 IN EFI_HANDLE ControllerHandle,
\r
270 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
\r
276 // Test to see if Arp SB is already installed.
\r
278 Status = gBS->OpenProtocol (
\r
280 &gEfiArpServiceBindingProtocolGuid,
\r
282 This->DriverBindingHandle,
\r
284 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
\r
286 if (Status == EFI_SUCCESS) {
\r
287 return EFI_ALREADY_STARTED;
\r
291 // Test to see if MNP SB is installed.
\r
293 Status = gBS->OpenProtocol (
\r
295 &gEfiManagedNetworkServiceBindingProtocolGuid,
\r
297 This->DriverBindingHandle,
\r
299 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
\r
307 Start this driver on ControllerHandle.
\r
309 @param This Protocol instance pointer.
\r
310 @param ControllerHandle Handle of device to bind driver to
\r
311 @param RemainingDevicePath Optional parameter use to pick a specific child
\r
314 @retval EFI_SUCCES This driver is added to ControllerHandle
\r
315 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
\r
316 @retval other This driver does not support this device
\r
321 ArpDriverBindingStart (
\r
322 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
323 IN EFI_HANDLE ControllerHandle,
\r
324 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
\r
328 ARP_SERVICE_DATA *ArpService;
\r
331 // Allocate a zero pool for ArpService.
\r
333 ArpService = AllocateZeroPool (sizeof(ARP_SERVICE_DATA));
\r
334 if (ArpService == NULL) {
\r
335 return EFI_OUT_OF_RESOURCES;
\r
339 // Initialize the arp service context data.
\r
341 Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);
\r
342 if (EFI_ERROR (Status)) {
\r
347 // Install the ARP service binding protocol.
\r
349 Status = gBS->InstallMultipleProtocolInterfaces (
\r
351 &gEfiArpServiceBindingProtocolGuid,
\r
352 &ArpService->ServiceBinding,
\r
355 if (EFI_ERROR (Status)) {
\r
360 // OK, start to receive arp packets from Mnp.
\r
362 Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);
\r
363 if (EFI_ERROR (Status)) {
\r
372 // On error, clean the arp service context data, and free the memory allocated.
\r
374 ArpCleanService (ArpService);
\r
375 gBS->FreePool (ArpService);
\r
382 Stop this driver on ControllerHandle.
\r
384 @param This Protocol instance pointer.
\r
385 @param ControllerHandle Handle of device to stop driver on
\r
386 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
\r
387 of children is zero stop the entire bus driver.
\r
388 @param ChildHandleBuffer List of Child Handles to Stop.
\r
390 @retval EFI_SUCCES This driver is removed ControllerHandle
\r
391 @retval other This driver was not removed from this device
\r
396 ArpDriverBindingStop (
\r
397 IN EFI_DRIVER_BINDING_PROTOCOL *This,
\r
398 IN EFI_HANDLE ControllerHandle,
\r
399 IN UINTN NumberOfChildren,
\r
400 IN EFI_HANDLE *ChildHandleBuffer
\r
404 EFI_HANDLE NicHandle;
\r
405 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
\r
406 ARP_SERVICE_DATA *ArpService;
\r
407 ARP_INSTANCE_DATA *Instance;
\r
410 // Get the NicHandle which the arp servicebinding is installed on.
\r
412 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
\r
413 if (NicHandle == NULL) {
\r
414 return EFI_DEVICE_ERROR;
\r
418 // Try to get the arp servicebinding protocol on the NicHandle.
\r
420 Status = gBS->OpenProtocol (
\r
422 &gEfiArpServiceBindingProtocolGuid,
\r
423 (VOID **)&ServiceBinding,
\r
424 This->DriverBindingHandle,
\r
426 EFI_OPEN_PROTOCOL_GET_PROTOCOL
\r
428 if (EFI_ERROR (Status)) {
\r
429 DEBUG ((EFI_D_ERROR, "ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));
\r
430 return EFI_DEVICE_ERROR;
\r
433 ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);
\r
435 if (NumberOfChildren == 0) {
\r
437 // Uninstall the ARP ServiceBinding protocol.
\r
439 gBS->UninstallMultipleProtocolInterfaces (
\r
441 &gEfiArpServiceBindingProtocolGuid,
\r
442 &ArpService->ServiceBinding,
\r
447 // Clean the arp servicebinding context data and free the memory allocated.
\r
449 ArpCleanService (ArpService);
\r
451 gBS->FreePool (ArpService);
\r
454 while (!IsListEmpty (&ArpService->ChildrenList)) {
\r
455 Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);
\r
457 ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
\r
460 ASSERT (IsListEmpty (&ArpService->PendingRequestTable));
\r
461 ASSERT (IsListEmpty (&ArpService->DeniedCacheTable));
\r
462 ASSERT (IsListEmpty (&ArpService->ResolvedCacheTable));
\r
465 return EFI_SUCCESS;
\r
469 Creates a child handle with a set of I/O services.
\r
471 @param This Protocol instance pointer.
\r
472 @param ChildHandle Pointer to the handle of the child to create. If
\r
473 it is NULL, then a new handle is created. If it is
\r
474 not NULL, then the I/O services are added to the
\r
475 existing child handle.
\r
477 @retval EFI_SUCCES The child handle was created with the I/O
\r
479 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
\r
481 @retval other The child handle was not created.
\r
486 ArpServiceBindingCreateChild (
\r
487 IN EFI_SERVICE_BINDING_PROTOCOL *This,
\r
488 IN EFI_HANDLE *ChildHandle
\r
492 ARP_SERVICE_DATA *ArpService;
\r
493 ARP_INSTANCE_DATA *Instance;
\r
497 if ((This == NULL) || (ChildHandle == NULL)) {
\r
498 return EFI_INVALID_PARAMETER;
\r
501 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
\r
504 // Allocate memory for the instance context data.
\r
506 Instance = AllocateZeroPool (sizeof(ARP_INSTANCE_DATA));
\r
507 if (Instance == NULL) {
\r
508 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: Failed to allocate memory for Instance.\n"));
\r
510 return EFI_OUT_OF_RESOURCES;
\r
514 // Init the instance context data.
\r
516 ArpInitInstance (ArpService, Instance);
\r
519 // Install the ARP protocol onto the ChildHandle.
\r
521 Status = gBS->InstallMultipleProtocolInterfaces (
\r
523 &gEfiArpProtocolGuid,
\r
524 (VOID *)&Instance->ArpProto,
\r
527 if (EFI_ERROR (Status)) {
\r
528 DEBUG ((EFI_D_ERROR, "ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));
\r
530 gBS->FreePool (Instance);
\r
535 // Save the ChildHandle.
\r
537 Instance->Handle = *ChildHandle;
\r
540 // Open the Managed Network protocol BY_CHILD.
\r
542 Status = gBS->OpenProtocol (
\r
543 ArpService->MnpChildHandle,
\r
544 &gEfiManagedNetworkProtocolGuid,
\r
546 gArpDriverBinding.DriverBindingHandle,
\r
548 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
\r
550 if (EFI_ERROR (Status)) {
\r
554 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
\r
557 // Insert the instance into children list managed by the arp service context data.
\r
559 InsertTailList (&ArpService->ChildrenList, &Instance->List);
\r
560 ArpService->ChildrenNumber++;
\r
562 gBS->RestoreTPL (OldTpl);
\r
566 if (EFI_ERROR (Status)) {
\r
568 gBS->CloseProtocol (
\r
569 ArpService->MnpChildHandle,
\r
570 &gEfiManagedNetworkProtocolGuid,
\r
571 gArpDriverBinding.DriverBindingHandle,
\r
575 gBS->UninstallMultipleProtocolInterfaces (
\r
577 &gEfiArpProtocolGuid,
\r
578 &Instance->ArpProto,
\r
583 // Free the allocated memory.
\r
585 gBS->FreePool (Instance);
\r
593 Destroys a child handle with a set of I/O services.
\r
595 @param This Protocol instance pointer.
\r
596 @param ChildHandle Handle of the child to destroy.
\r
598 @retval EFI_SUCCES The I/O services were removed from the child
\r
600 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
\r
601 that are being removed.
\r
602 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
\r
603 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
\r
604 its I/O services are being used.
\r
605 @retval other The child handle was not destroyed.
\r
610 ArpServiceBindingDestroyChild (
\r
611 IN EFI_SERVICE_BINDING_PROTOCOL *This,
\r
612 IN EFI_HANDLE ChildHandle
\r
616 ARP_SERVICE_DATA *ArpService;
\r
617 ARP_INSTANCE_DATA *Instance;
\r
618 EFI_ARP_PROTOCOL *Arp;
\r
621 if ((This == NULL) || (ChildHandle == NULL)) {
\r
622 return EFI_INVALID_PARAMETER;
\r
625 ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
\r
628 // Get the arp protocol.
\r
630 Status = gBS->OpenProtocol (
\r
632 &gEfiArpProtocolGuid,
\r
634 ArpService->ImageHandle,
\r
636 EFI_OPEN_PROTOCOL_GET_PROTOCOL
\r
638 if (EFI_ERROR (Status)) {
\r
639 return EFI_UNSUPPORTED;
\r
642 Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);
\r
644 if (Instance->Destroyed) {
\r
645 return EFI_SUCCESS;
\r
649 // Use the Destroyed as a flag to avoid re-entrance.
\r
651 Instance->Destroyed = TRUE;
\r
654 // Close the Managed Network protocol.
\r
656 gBS->CloseProtocol (
\r
657 ArpService->MnpChildHandle,
\r
658 &gEfiManagedNetworkProtocolGuid,
\r
659 gArpDriverBinding.DriverBindingHandle,
\r
664 // Uninstall the ARP protocol.
\r
666 Status = gBS->UninstallMultipleProtocolInterfaces (
\r
668 &gEfiArpProtocolGuid,
\r
669 &Instance->ArpProto,
\r
672 if (EFI_ERROR (Status)) {
\r
673 DEBUG ((EFI_D_ERROR, "ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",
\r
676 Instance->Destroyed = FALSE;
\r
680 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
\r
682 if (Instance->Configured) {
\r
684 // Delete the related cache entry.
\r
686 ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);
\r
689 // Reset the instance configuration.
\r
691 ArpConfigureInstance (Instance, NULL);
\r
695 // Remove this instance from the ChildrenList.
\r
697 RemoveEntryList (&Instance->List);
\r
698 ArpService->ChildrenNumber--;
\r
700 gBS->RestoreTPL (OldTpl);
\r
702 gBS->FreePool (Instance);
\r
708 The entry point for Arp driver which installs the driver binding and component name
\r
709 protocol on its ImageHandle.
\r
711 @param ImageHandle The image handle of the driver.
\r
712 @param SystemTable The system table.
\r
714 @retval EFI_SUCCES if the driver binding and component name protocols are successfully
\r
715 @retval Others Failed to install the protocols.
\r
720 ArpDriverEntryPoint (
\r
721 IN EFI_HANDLE ImageHandle,
\r
722 IN EFI_SYSTEM_TABLE *SystemTable
\r
725 return EfiLibInstallDriverBindingComponentName2 (
\r
728 &gArpDriverBinding,
\r
730 &gArpComponentName,
\r
731 &gArpComponentName2
\r