summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/Network/ArpDxe
diff options
context:
space:
mode:
authorvanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-30 02:37:10 +0000
committervanjeff <vanjeff@6f19259b-4bc3-4df7-8a09-765794883524>2007-07-30 02:37:10 +0000
commit772db4bb33ae66fa20e39f786b5f80d107d450a5 (patch)
tree206a2d4756e0f7e245e08ca75f3ba10df2e1cf7a /MdeModulePkg/Universal/Network/ArpDxe
parenteca7eaf49be5f23e3c79270621df7097ef585349 (diff)
downloadedk2-772db4bb33ae66fa20e39f786b5f80d107d450a5.zip
edk2-772db4bb33ae66fa20e39f786b5f80d107d450a5.tar.gz
edk2-772db4bb33ae66fa20e39f786b5f80d107d450a5.tar.bz2
Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3492 6f19259b-4bc3-4df7-8a09-765794883524
Diffstat (limited to 'MdeModulePkg/Universal/Network/ArpDxe')
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpDebug.h30
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c763
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.h84
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf59
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.msa72
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c1628
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.h341
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ArpMain.c727
-rw-r--r--MdeModulePkg/Universal/Network/ArpDxe/ComponentName.c156
9 files changed, 3860 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpDebug.h b/MdeModulePkg/Universal/Network/ArpDxe/ArpDebug.h
new file mode 100644
index 0000000..05f542d
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpDebug.h
@@ -0,0 +1,30 @@
+/** @file
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpDebug.h
+
+Abstract:
+
+
+**/
+
+#ifndef _ARP_DEBUG_H_
+#define _ARP_DEBUG_H_
+
+
+#define ARP_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE ("Arp", PrintArg)
+#define ARP_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING ("Arp", PrintArg)
+#define ARP_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR ("Arp", PrintArg)
+
+#endif
+
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c b/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
new file mode 100644
index 0000000..2c10857
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.c
@@ -0,0 +1,763 @@
+/** @file
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpDriver.c
+
+Abstract:
+
+
+**/
+
+
+#include "ArpDriver.h"
+#include "ArpImpl.h"
+
+EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {
+ ArpDriverBindingSupported,
+ ArpDriverBindingStart,
+ ArpDriverBindingStop,
+ 0xa,
+ NULL,
+ NULL
+};
+
+
+/**
+ Create and initialize the arp service context data.
+
+ @param ImageHandle The image handle representing the loaded driver
+ image.
+ @param ControllerHandle The controller handle the driver binds to.
+ @param ArpService Pointer to the buffer containing the arp service
+ context data.
+
+ @retval EFI_SUCCESS The arp service context is initialized.
+ @retval other Failed to initialize the arp service context.
+
+**/
+STATIC
+EFI_STATUS
+ArpCreateService (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_HANDLE ControllerHandle,
+ IN ARP_SERVICE_DATA *ArpService
+ )
+{
+ EFI_STATUS Status;
+
+ ASSERT (ArpService != NULL);
+
+ ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;
+
+ //
+ // Init the servicebinding protocol members.
+ //
+ ArpService->ServiceBinding.CreateChild = ArpServiceBindingCreateChild;
+ ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;
+
+ //
+ // Save the handles.
+ //
+ ArpService->ImageHandle = ImageHandle;
+ ArpService->ControllerHandle = ControllerHandle;
+
+ //
+ // Create a MNP child instance.
+ //
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ ImageHandle,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ &ArpService->MnpChildHandle
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Open the MNP protocol.
+ //
+ Status = gBS->OpenProtocol (
+ ArpService->MnpChildHandle,
+ &gEfiManagedNetworkProtocolGuid,
+ (VOID **)&ArpService->Mnp,
+ ImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_BY_DRIVER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_EXIT;
+ }
+
+ //
+ // Get the underlayer Snp mode data.
+ //
+ Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);
+ if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {
+ goto ERROR_EXIT;
+ }
+
+ if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {
+ //
+ // Only support the ethernet.
+ //
+ Status = EFI_UNSUPPORTED;
+ goto ERROR_EXIT;
+ }
+
+ //
+ // Set the Mnp config parameters.
+ //
+ ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;
+ ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;
+ ArpService->MnpConfigData.ProtocolTypeFilter = ARP_ETHER_PROTO_TYPE;
+ ArpService->MnpConfigData.EnableUnicastReceive = TRUE;
+ ArpService->MnpConfigData.EnableMulticastReceive = FALSE;
+ ArpService->MnpConfigData.EnableBroadcastReceive = TRUE;
+ ArpService->MnpConfigData.EnablePromiscuousReceive = FALSE;
+ ArpService->MnpConfigData.FlushQueuesOnReset = TRUE;
+ ArpService->MnpConfigData.EnableReceiveTimestamps = FALSE;
+ ArpService->MnpConfigData.DisableBackgroundPolling = FALSE;
+
+ //
+ // Configure the Mnp child.
+ //
+ Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);
+ if (EFI_ERROR (Status)) {
+ goto ERROR_EXIT;
+ }
+
+ //
+ // Create the event used in the RxToken.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ NET_TPL_EVENT,
+ ArpOnFrameRcvd,
+ ArpService,
+ &ArpService->RxToken.Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_EXIT;
+ }
+
+ //
+ // Create the Arp heartbeat timer.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL | EVT_TIMER,
+ NET_TPL_TIMER,
+ ArpTimerHandler,
+ ArpService,
+ &ArpService->PeriodicTimer
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_EXIT;
+ }
+
+ //
+ // Start the heartbeat timer.
+ //
+ Status = gBS->SetTimer (
+ ArpService->PeriodicTimer,
+ TimerPeriodic,
+ ARP_PERIODIC_TIMER_INTERVAL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR_EXIT;
+ }
+
+ //
+ // Init the lock.
+ //
+ NET_LOCK_INIT (&ArpService->Lock);
+
+ //
+ // Init the lists.
+ //
+ NetListInit (&ArpService->ChildrenList);
+ NetListInit (&ArpService->PendingRequestTable);
+ NetListInit (&ArpService->DeniedCacheTable);
+ NetListInit (&ArpService->ResolvedCacheTable);
+
+ERROR_EXIT:
+
+ return Status;
+}
+
+
+/**
+ Clean the arp service context data.
+
+ @param ArpService Pointer to the buffer containing the arp service
+ context data.
+
+ @return None.
+
+**/
+STATIC
+VOID
+ArpCleanService (
+ IN ARP_SERVICE_DATA *ArpService
+ )
+{
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
+
+ if (ArpService->PeriodicTimer != NULL) {
+ //
+ // Cancle and close the PeriodicTimer.
+ //
+ gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);
+ gBS->CloseEvent (ArpService->PeriodicTimer);
+ }
+
+ if (ArpService->RxToken.Event != NULL) {
+ //
+ // Cancle the RxToken and close the event in the RxToken.
+ //
+ ArpService->Mnp->Cancel (ArpService->Mnp, NULL);
+ gBS->CloseEvent (ArpService->RxToken.Event);
+ }
+
+ if (ArpService->Mnp != NULL) {
+ //
+ // Reset the Mnp child and close the Mnp protocol.
+ //
+ ArpService->Mnp->Configure (ArpService->Mnp, NULL);
+ gBS->CloseProtocol (
+ ArpService->MnpChildHandle,
+ &gEfiManagedNetworkProtocolGuid,
+ ArpService->ImageHandle,
+ ArpService->ControllerHandle
+ );
+ }
+
+ if (ArpService->MnpChildHandle != NULL) {
+ //
+ // Destroy the mnp child.
+ //
+ NetLibDestroyServiceChild(
+ ArpService->ControllerHandle,
+ ArpService->ImageHandle,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ ArpService->MnpChildHandle
+ );
+ }
+}
+
+
+/**
+ Test to see if this driver supports ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to test.
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCES This driver supports this device
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.
+ @retval other This driver does not support this device.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Test to see if Arp SB is already installed.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiArpServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (Status == EFI_SUCCESS) {
+ return EFI_ALREADY_STARTED;
+ }
+
+ //
+ // Test to see if MNP SB is installed.
+ //
+ Status = gBS->OpenProtocol (
+ ControllerHandle,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ NULL,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+
+ return Status;
+}
+
+
+/**
+ Start this driver on ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to bind driver to
+ @param RemainingDevicePath Optional parameter use to pick a specific child
+ device to start.
+
+ @retval EFI_SUCCES This driver is added to ControllerHandle
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
+ @retval other This driver does not support this device
+
+**/
+EFI_STATUS
+EFIAPI
+ArpDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ ARP_SERVICE_DATA *ArpService;
+
+ //
+ // Allocate a zero pool for ArpService.
+ //
+ ArpService = NetAllocateZeroPool (sizeof(ARP_SERVICE_DATA));
+ if (ArpService == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize the arp service context data.
+ //
+ Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);
+ if (EFI_ERROR (Status)) {
+ goto ERROR;
+ }
+
+ //
+ // Install the ARP service binding protocol.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &ControllerHandle,
+ &gEfiArpServiceBindingProtocolGuid,
+ &ArpService->ServiceBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR;
+ }
+
+ //
+ // OK, start to receive arp packets from Mnp.
+ //
+ Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);
+ if (EFI_ERROR (Status)) {
+ goto ERROR;
+ }
+
+ return Status;
+
+ERROR:
+
+ //
+ // On error, clean the arp service context data, and free the memory allocated.
+ //
+ ArpCleanService (ArpService);
+ NetFreePool (ArpService);
+
+ return Status;
+}
+
+
+/**
+ Stop this driver on ControllerHandle.
+
+ @param This Protocol instance pointer.
+ @param ControllerHandle Handle of device to stop driver on
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
+ of children is zero stop the entire bus driver.
+ @param ChildHandleBuffer List of Child Handles to Stop.
+
+ @retval EFI_SUCCES This driver is removed ControllerHandle
+ @retval other This driver was not removed from this device
+
+**/
+EFI_STATUS
+EFIAPI
+ArpDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE NicHandle;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ ARP_SERVICE_DATA *ArpService;
+ ARP_INSTANCE_DATA *Instance;
+
+ //
+ // Get the NicHandle which the arp servicebinding is installed on.
+ //
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
+ if (NicHandle == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Try to get the arp servicebinding protocol on the NicHandle.
+ //
+ Status = gBS->OpenProtocol (
+ NicHandle,
+ &gEfiArpServiceBindingProtocolGuid,
+ (VOID **)&ServiceBinding,
+ This->DriverBindingHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ ARP_DEBUG_ERROR (("ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));
+ return Status;
+ }
+
+ ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);
+
+ while (!NetListIsEmpty (&ArpService->ChildrenList)) {
+ //
+ // Iterate all the instances.
+ //
+ Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);
+
+ //
+ // Destroy this arp child.
+ //
+ ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);
+ }
+
+ ASSERT (NetListIsEmpty (&ArpService->PendingRequestTable));
+ ASSERT (NetListIsEmpty (&ArpService->DeniedCacheTable));
+ ASSERT (NetListIsEmpty (&ArpService->ResolvedCacheTable));
+
+ //
+ // Uninstall the ARP ServiceBinding protocol.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ NicHandle,
+ &gEfiArpServiceBindingProtocolGuid,
+ &ArpService->ServiceBinding,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ARP_DEBUG_ERROR (("ArpDriverBindingStop: Failed to uninstall ArpSb, %r.\n", Status));
+ return Status;
+ }
+
+ //
+ // Clean the arp servicebinding context data and free the memory allocated.
+ //
+ ArpCleanService (ArpService);
+ NetFreePool (ArpService);
+
+ return Status;
+}
+
+
+/**
+ Creates a child handle with a set of I/O services.
+
+ @param This Protocol instance pointer.
+ @param ChildHandle Pointer to the handle of the child to create. If
+ it is NULL, then a new handle is created. If it is
+ not NULL, then the I/O services are added to the
+ existing child handle.
+
+ @retval EFI_SUCCES The child handle was created with the I/O
+ services.
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
+ the child.
+ @retval other The child handle was not created.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ )
+{
+ EFI_STATUS Status;
+ ARP_SERVICE_DATA *ArpService;
+ ARP_INSTANCE_DATA *Instance;
+ VOID *Mnp;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
+
+ //
+ // Allocate memory for the instance context data.
+ //
+ Instance = NetAllocateZeroPool (sizeof(ARP_INSTANCE_DATA));
+ if (Instance == NULL) {
+ ARP_DEBUG_ERROR (("ArpSBCreateChild: Failed to allocate memory for Instance.\n"));
+
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Init the instance context data.
+ //
+ ArpInitInstance (ArpService, Instance);
+
+ //
+ // Install the ARP protocol onto the ChildHandle.
+ //
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiArpProtocolGuid,
+ (VOID *)&Instance->ArpProto,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ARP_DEBUG_ERROR (("ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));
+
+ NetFreePool (Instance);
+ return Status;
+ }
+
+ //
+ // Save the ChildHandle.
+ //
+ Instance->Handle = *ChildHandle;
+
+ //
+ // Open the Managed Network protocol BY_CHILD.
+ //
+ Status = gBS->OpenProtocol (
+ ArpService->MnpChildHandle,
+ &gEfiManagedNetworkProtocolGuid,
+ (VOID **) &Mnp,
+ gArpDriverBinding.DriverBindingHandle,
+ Instance->Handle,
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
+ );
+ if (EFI_ERROR (Status)) {
+ goto ERROR;
+ }
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+
+ Status = EFI_ACCESS_DENIED;
+ goto ERROR;
+ }
+
+ //
+ // Insert the instance into children list managed by the arp service context data.
+ //
+ NetListInsertTail (&ArpService->ChildrenList, &Instance->List);
+ ArpService->ChildrenNumber++;
+
+ NET_UNLOCK (&ArpService->Lock);
+
+ERROR:
+
+ if (EFI_ERROR (Status)) {
+
+ gBS->CloseProtocol (
+ ArpService->MnpChildHandle,
+ &gEfiManagedNetworkProtocolGuid,
+ gArpDriverBinding.DriverBindingHandle,
+ Instance->Handle
+ );
+
+ gBS->UninstallMultipleProtocolInterfaces (
+ Instance->Handle,
+ &gEfiArpProtocolGuid,
+ &Instance->ArpProto,
+ NULL
+ );
+
+ //
+ // Free the allocated memory.
+ //
+ NetFreePool (Instance);
+ }
+
+ return Status;
+}
+
+
+/**
+ Destroys a child handle with a set of I/O services.
+
+ @param This Protocol instance pointer.
+ @param ChildHandle Handle of the child to destroy.
+
+ @retval EFI_SUCCES The I/O services were removed from the child
+ handle.
+ @retval EFI_UNSUPPORTED The child handle does not support the I/O services
+ that are being removed.
+ @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
+ @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
+ its I/O services are being used.
+ @retval other The child handle was not destroyed.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ EFI_STATUS Status;
+ ARP_SERVICE_DATA *ArpService;
+ ARP_INSTANCE_DATA *Instance;
+ EFI_ARP_PROTOCOL *Arp;
+
+ if ((This == NULL) || (ChildHandle == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ArpService = ARP_SERVICE_DATA_FROM_THIS (This);
+
+ //
+ // Get the arp protocol.
+ //
+ Status = gBS->OpenProtocol (
+ ChildHandle,
+ &gEfiArpProtocolGuid,
+ (VOID **)&Arp,
+ ArpService->ImageHandle,
+ ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);
+
+ if (Instance->Destroyed) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Use the Destroyed as a flag to avoid re-entrance.
+ //
+ Instance->Destroyed = TRUE;
+
+ //
+ // Close the Managed Network protocol.
+ //
+ gBS->CloseProtocol (
+ ArpService->MnpChildHandle,
+ &gEfiManagedNetworkProtocolGuid,
+ gArpDriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+
+ //
+ // Uninstall the ARP protocol.
+ //
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ ChildHandle,
+ &gEfiArpProtocolGuid,
+ &Instance->ArpProto,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ ARP_DEBUG_ERROR (("ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",
+ Status));
+
+ Instance->Destroyed = FALSE;
+ return Status;
+ }
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ Instance->Destroyed = FALSE;
+ return EFI_ACCESS_DENIED;
+ }
+
+ if (Instance->Configured) {
+ //
+ // Delete the related cache entry.
+ //
+ ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);
+
+ //
+ // Reset the instance configuration.
+ //
+ ArpConfigureInstance (Instance, NULL);
+ }
+
+ //
+ // Remove this instance from the ChildrenList.
+ //
+ NetListRemoveEntry (&Instance->List);
+ ArpService->ChildrenNumber--;
+
+ NET_UNLOCK (&ArpService->Lock);
+
+ NetFreePool (Instance);
+
+ return Status;
+}
+
+//@MT: EFI_DRIVER_ENTRY_POINT (ArpDriverEntryPoint)
+
+EFI_STATUS
+EFIAPI
+ArpDriverEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+/*++
+
+Routine Description:
+
+ The entry point for Arp driver which installs the driver binding and component name
+ protocol on its ImageHandle.
+
+Arguments:
+
+ ImageHandle - The image handle of the driver.
+ SystemTable - The system table.
+
+Returns:
+
+ EFI_SUCCESS - if the driver binding and component name protocols are successfully
+ installed, otherwise if failed.
+
+--*/
+{
+ return NetLibInstallAllDriverProtocols (
+ ImageHandle,
+ SystemTable,
+ &gArpDriverBinding,
+ ImageHandle,
+ &gArpComponentName,
+ NULL,
+ NULL
+ );
+}
+
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.h b/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.h
new file mode 100644
index 0000000..93526c7
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpDriver.h
@@ -0,0 +1,84 @@
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpDriver.c
+
+Abstract:
+
+
+**/
+
+#ifndef _ARP_DRIVER_H_
+#define _ARP_DRIVER_H_
+
+
+#include <PiDxe.h>
+
+#include <Protocol/Arp.h>
+#include <Protocol/ManagedNetwork.h>
+#include <Protocol/ServiceBinding.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+#include "ArpDebug.h"
+
+//
+// Global variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gArpComponentName;
+
+EFI_STATUS
+EFIAPI
+ArpDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+ArpServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+EFI_STATUS
+EFIAPI
+ArpServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+
+#endif
+
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf b/MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
new file mode 100644
index 0000000..4cc9b2e
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf
@@ -0,0 +1,59 @@
+#/** @file
+# Component description file for ARP module
+#
+# Copyright (c) 2006, Intel Corporation
+#
+# All rights reserved. This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+#
+#**/
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = ArpDxe
+ FILE_GUID = 529D3F93-E8E9-4e73-B1E1-BDF6A9D50113
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ EDK_RELEASE_VERSION = 0x00020000
+ EFI_SPECIFICATION_VERSION = 0x00020000
+
+ ENTRY_POINT = ArpDriverEntryPoint
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ ArpMain.c
+ ArpDriver.h
+ ComponentName.c
+ ArpImpl.h
+ ArpImpl.c
+ ArpDebug.h
+ ArpDriver.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+
+[LibraryClasses]
+ UefiLib
+ UefiBootServicesTableLib
+ UefiDriverEntryPoint
+ DebugLib
+ NetLib
+
+
+[Protocols]
+ gEfiManagedNetworkServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiArpServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiManagedNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+ gEfiArpProtocolGuid # PROTOCOL ALWAYS_CONSUMED
+
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.msa b/MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.msa
new file mode 100644
index 0000000..89178fa
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.msa
@@ -0,0 +1,72 @@
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <MsaHeader>
+ <ModuleName>Arp</ModuleName>
+ <ModuleType>DXE_DRIVER</ModuleType>
+ <GuidValue>529D3F93-E8E9-4e73-B1E1-BDF6A9D50113</GuidValue>
+ <Version>1.0</Version>
+ <Abstract>Component name for module Arp</Abstract>
+ <Description>FIX ME!</Description>
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>
+ <License>All rights reserved. This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>
+ </MsaHeader>
+ <ModuleDefinitions>
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>
+ <BinaryModule>false</BinaryModule>
+ <OutputFileBasename>Arp</OutputFileBasename>
+ </ModuleDefinitions>
+ <LibraryClassDefinitions>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>DebugLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiDriverEntryPoint</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiBootServicesTableLib</Keyword>
+ </LibraryClass>
+ <LibraryClass Usage="ALWAYS_CONSUMED">
+ <Keyword>UefiLib</Keyword>
+ </LibraryClass>
+ </LibraryClassDefinitions>
+ <SourceFiles>
+ <Filename>ArpDriver.c</Filename>
+ <Filename>ArpDebug.h</Filename>
+ <Filename>ArpImpl.c</Filename>
+ <Filename>ArpImpl.h</Filename>
+ <Filename>ComponentName.c</Filename>
+ <Filename>ArpDriver.h</Filename>
+ <Filename>ArpMain.c</Filename>
+ </SourceFiles>
+ <PackageDependencies>
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>
+ </PackageDependencies>
+ <Protocols>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiArpProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiManagedNetworkProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiArpServiceBindingProtocolGuid</ProtocolCName>
+ </Protocol>
+ <Protocol Usage="ALWAYS_CONSUMED">
+ <ProtocolCName>gEfiManagedNetworkServiceBindingProtocolGuid</ProtocolCName>
+ </Protocol>
+ </Protocols>
+ <Externs>
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>
+ <Extern>
+ <ModuleEntryPoint>ArpDriverEntryPoint</ModuleEntryPoint>
+ </Extern>
+ </Externs>
+</ModuleSurfaceArea> \ No newline at end of file
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c b/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
new file mode 100644
index 0000000..93b4c10
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.c
@@ -0,0 +1,1628 @@
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpImpl.c
+
+Abstract:
+
+
+**/
+
+
+#include "ArpImpl.h"
+#include "ArpDebug.h"
+
+EFI_ARP_PROTOCOL mEfiArpProtocolTemplate = {
+ ArpConfigure,
+ ArpAdd,
+ ArpFind,
+ ArpDelete,
+ ArpFlush,
+ ArpRequest,
+ ArpCancel
+};
+
+
+/**
+ Initialize the instance context data.
+
+ @param ArpService Pointer to the arp service context data this
+ instance belongs to.
+ @param Instance Pointer to the instance context data.
+
+ @return None.
+
+**/
+VOID
+ArpInitInstance (
+ IN ARP_SERVICE_DATA *ArpService,
+ IN ARP_INSTANCE_DATA *Instance
+ )
+{
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
+
+ Instance->Signature = ARP_INSTANCE_DATA_SIGNATURE;
+ Instance->ArpService = ArpService;
+
+ CopyMem (&Instance->ArpProto, &mEfiArpProtocolTemplate, sizeof (ARP_SERVICE_DATA));
+
+ Instance->Configured = FALSE;
+ Instance->Destroyed = FALSE;
+
+ NetListInit (&Instance->List);
+}
+
+
+/**
+ Process the Arp packets received from Mnp, the procedure conforms to RFC826.
+
+ @param Event The Event this notify function registered to.
+ @param Context Pointer to the context data registerd to the
+ Event.
+
+ @return None.
+
+**/
+VOID
+EFIAPI
+ArpOnFrameRcvd (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ ARP_SERVICE_DATA *ArpService;
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken;
+ EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;
+ ARP_HEAD *Head;
+ ARP_ADDRESS ArpAddress;
+ ARP_CACHE_ENTRY *CacheEntry;
+ NET_LIST_ENTRY *Entry;
+ ARP_INSTANCE_DATA *Instance;
+ EFI_ARP_CONFIG_DATA *ConfigData;
+ NET_ARP_ADDRESS SenderAddress[2];
+ BOOLEAN ProtoMatched;
+ BOOLEAN IsTarget;
+ BOOLEAN MergeFlag;
+
+ ArpService = (ARP_SERVICE_DATA *)Context;
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
+
+ RxToken = &ArpService->RxToken;
+
+ if (RxToken->Status == EFI_ABORTED) {
+ //
+ // The Token is aborted, possibly by arp itself, just return and the receiving
+ // process is stopped.
+ //
+ return;
+ }
+
+ if (EFI_ERROR (RxToken->Status)) {
+ //
+ // Restart the receiving if any other error Status occurs.
+ //
+ goto RESTART_RECEIVE;
+ }
+
+ //
+ // Status is EFI_SUCCESS, process the received frame.
+ //
+ RxData = RxToken->Packet.RxData;
+ Head = (ARP_HEAD *) RxData->PacketData;
+
+ //
+ // Convert the byte order of the multi-byte fields.
+ //
+ Head->HwType = NTOHS (Head->HwType);
+ Head->ProtoType = NTOHS (Head->ProtoType);
+ Head->OpCode = NTOHS (Head->OpCode);
+
+ if ((Head->HwType != ArpService->SnpMode.IfType) ||
+ (Head->HwAddrLen != ArpService->SnpMode.HwAddressSize) ||
+ (RxData->ProtocolType != ARP_ETHER_PROTO_TYPE)) {
+ //
+ // The hardware type or the hardware address length doesn't match.
+ // There is a sanity check for the protocol type too.
+ //
+ goto RECYCLE_RXDATA;
+ }
+
+ //
+ // Set the pointers to the addresses contained in the arp packet.
+ //
+ ArpAddress.SenderHwAddr = (UINT8 *)(Head + 1);
+ ArpAddress.SenderProtoAddr = ArpAddress.SenderHwAddr + Head->HwAddrLen;
+ ArpAddress.TargetHwAddr = ArpAddress.SenderProtoAddr + Head->ProtoAddrLen;
+ ArpAddress.TargetProtoAddr = ArpAddress.TargetHwAddr + Head->HwAddrLen;
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ ARP_DEBUG_ERROR (("ArpOnFrameRcvd: Faild to acquire the CacheTableLock.\n"));
+ goto RECYCLE_RXDATA;
+ }
+
+ SenderAddress[Hardware].Type = Head->HwType;
+ SenderAddress[Hardware].Length = Head->HwAddrLen;
+ SenderAddress[Hardware].AddressPtr = ArpAddress.SenderHwAddr;
+
+ SenderAddress[Protocol].Type = Head->ProtoType;
+ SenderAddress[Protocol].Length = Head->ProtoAddrLen;
+ SenderAddress[Protocol].AddressPtr = ArpAddress.SenderProtoAddr;
+
+ //
+ // First, check the denied cache table.
+ //
+ CacheEntry = ArpFindDeniedCacheEntry (
+ ArpService,
+ &SenderAddress[Protocol],
+ &SenderAddress[Hardware]
+ );
+ if (CacheEntry != NULL) {
+ //
+ // This address (either hardware or protocol address, or both) is configured to
+ // be a deny entry, silently skip the normal process.
+ //
+ goto UNLOCK_EXIT;
+ }
+
+ ProtoMatched = FALSE;
+ IsTarget = FALSE;
+ Instance = NULL;
+ NET_LIST_FOR_EACH (Entry, &ArpService->ChildrenList) {
+ //
+ // Iterate all the children.
+ //
+ Instance = NET_LIST_USER_STRUCT (Entry, ARP_INSTANCE_DATA, List);
+ NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
+ ConfigData = &Instance->ConfigData;
+
+ if ((Instance->Configured) &&
+ (Head->ProtoType == ConfigData->SwAddressType) &&
+ (Head->ProtoAddrLen == ConfigData->SwAddressLength)) {
+ //
+ // The protocol type is matched for the received arp packet.
+ //
+ ProtoMatched = TRUE;
+ if (0 == NetCompareMem (
+ (VOID *)ArpAddress.TargetProtoAddr,
+ ConfigData->StationAddress,
+ ConfigData->SwAddressLength
+ )) {
+ //
+ // The arp driver has the target address required by the received arp packet.
+ //
+ IsTarget = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!ProtoMatched) {
+ //
+ // Protocol type unmatchable, skip.
+ //
+ goto UNLOCK_EXIT;
+ }
+
+ //
+ // Check whether the sender's address information is already in the cache.
+ //
+ MergeFlag = FALSE;
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->ResolvedCacheTable,
+ NULL,
+ ByProtoAddress,
+ &SenderAddress[Protocol],
+ NULL
+ );
+ if (CacheEntry != NULL) {
+ //
+ // Update the entry with the new information.
+ //
+ ArpFillAddressInCacheEntry (CacheEntry, &SenderAddress[Hardware], NULL);
+ CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
+ MergeFlag = TRUE;
+ }
+
+ if (!IsTarget) {
+ //
+ // This arp packet isn't targeted to us, skip now.
+ //
+ goto UNLOCK_EXIT;
+ }
+
+ if (!MergeFlag) {
+ //
+ // Add the triplet <protocol type, sender protocol address, sender hardware address>
+ // to the translation table.
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->PendingRequestTable,
+ NULL,
+ ByProtoAddress,
+ &SenderAddress[Protocol],
+ NULL
+ );
+ if (CacheEntry == NULL) {
+ //
+ // Allocate a new CacheEntry.
+ //
+ CacheEntry = ArpAllocCacheEntry (NULL);
+ if (CacheEntry == NULL) {
+ goto UNLOCK_EXIT;
+ }
+ }
+
+ NetListRemoveEntry (&CacheEntry->List);
+
+ //
+ // Fill the addresses into the CacheEntry.
+ //
+ ArpFillAddressInCacheEntry (
+ CacheEntry,
+ &SenderAddress[Hardware],
+ &SenderAddress[Protocol]
+ );
+
+ //
+ // Inform the user.
+ //
+ ArpAddressResolved (CacheEntry, NULL, NULL);
+
+ //
+ // Add this entry into the ResolvedCacheTable
+ //
+ NetListInsertHead (&ArpService->ResolvedCacheTable, &CacheEntry->List);
+ }
+
+ if (Head->OpCode == ARP_OPCODE_REQUEST) {
+ //
+ // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry
+ // is not NULL.
+ //
+ ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REPLY);
+ }
+
+UNLOCK_EXIT:
+
+ NET_UNLOCK (&ArpService->Lock);
+
+RECYCLE_RXDATA:
+
+ //
+ // Signal Mnp to recycle the RxData.
+ //
+ gBS->SignalEvent (RxData->RecycleEvent);
+
+RESTART_RECEIVE:
+
+ //
+ // Continue to receive packets from Mnp.
+ //
+ Status = ArpService->Mnp->Receive (ArpService->Mnp, RxToken);
+
+ DEBUG_CODE (
+ if (EFI_ERROR (Status)) {
+ ARP_DEBUG_ERROR (("ArpOnFrameRcvd: ArpService->Mnp->Receive "
+ "failed, %r\n.", Status));
+ }
+ );
+}
+
+
+/**
+ Process the already sent arp packets.
+
+ @param Event The Event this notify function registered to.
+ @param Context Pointer to the context data registerd to the
+ Event.
+
+ @return None.
+
+**/
+VOID
+EFIAPI
+ArpOnFrameSent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
+ EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
+
+ ASSERT (Context != NULL);
+
+ TxToken = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *)Context;
+ TxData = TxToken->Packet.TxData;
+
+ DEBUG_CODE (
+ if (EFI_ERROR (TxToken->Status)) {
+ ARP_DEBUG_ERROR (("ArpOnFrameSent: TxToken->Status, %r.\n", TxToken->Status));
+ }
+ );
+
+ //
+ // Free the allocated memory and close the event.
+ //
+ NetFreePool (TxData->FragmentTable[0].FragmentBuffer);
+ NetFreePool (TxData);
+ gBS->CloseEvent (TxToken->Event);
+ NetFreePool (TxToken);
+}
+
+
+/**
+ Process the arp cache olding and drive the retrying arp requests.
+
+ @param Event The Event this notify function registered to.
+ @param Context Pointer to the context data registerd to the
+ Event.
+
+ @return None.
+
+**/
+VOID
+EFIAPI
+ArpTimerHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ ARP_SERVICE_DATA *ArpService;
+ NET_LIST_ENTRY *Entry;
+ NET_LIST_ENTRY *NextEntry;
+ NET_LIST_ENTRY *ContextEntry;
+ ARP_CACHE_ENTRY *CacheEntry;
+ USER_REQUEST_CONTEXT *RequestContext;
+
+ ASSERT (Context != NULL);
+ ArpService = (ARP_SERVICE_DATA *)Context;
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ return;
+ }
+
+ //
+ // Iterate all the pending requests to see whether a retry is needed to send out
+ // or the request finally fails because the retry time reaches the limitation.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
+
+ if (CacheEntry->NextRetryTime <= ARP_PERIODIC_TIMER_INTERVAL) {
+ //
+ // Timeout, if we can retry more, send out the request again, otherwise abort
+ // this request.
+ //
+ if (CacheEntry->RetryCount == 0) {
+ //
+ // Abort this request.
+ //
+ ArpAddressResolved (CacheEntry, NULL, NULL);
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));
+
+ NetListRemoveEntry (&CacheEntry->List);
+ NetFreePool (CacheEntry);
+ } else {
+ //
+ // resend the ARP request.
+ //
+ ASSERT (!NetListIsEmpty(&CacheEntry->UserRequestList));
+
+ ContextEntry = CacheEntry->UserRequestList.ForwardLink;
+ RequestContext = NET_LIST_USER_STRUCT (ContextEntry, USER_REQUEST_CONTEXT, List);
+
+ ArpSendFrame (RequestContext->Instance, CacheEntry, ARP_OPCODE_REQUEST);
+
+ CacheEntry->RetryCount--;
+ CacheEntry->NextRetryTime = RequestContext->Instance->ConfigData.RetryTimeOut;
+ }
+ } else {
+ //
+ // Update the NextRetryTime.
+ //
+ CacheEntry->NextRetryTime -= ARP_PERIODIC_TIMER_INTERVAL;
+ }
+ }
+
+ //
+ // Check the timeouts for the DeniedCacheTable.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->DeniedCacheTable) {
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));
+
+ if (CacheEntry->DefaultDecayTime == 0) {
+ //
+ // It's a static entry, skip it.
+ //
+ continue;
+ }
+
+ if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {
+ //
+ // Time out, remove it.
+ //
+ NetListRemoveEntry (&CacheEntry->List);
+ NetFreePool (CacheEntry);
+ } else {
+ //
+ // Update the DecayTime.
+ //
+ CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;
+ }
+ }
+
+ //
+ // Check the timeouts for the ResolvedCacheTable.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->ResolvedCacheTable) {
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));
+
+ if (CacheEntry->DefaultDecayTime == 0) {
+ //
+ // It's a static entry, skip it.
+ //
+ continue;
+ }
+
+ if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {
+ //
+ // Time out, remove it.
+ //
+ NetListRemoveEntry (&CacheEntry->List);
+ NetFreePool (CacheEntry);
+ } else {
+ //
+ // Update the DecayTime.
+ //
+ CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;
+ }
+ }
+
+ NET_UNLOCK (&ArpService->Lock);
+}
+
+
+/**
+ Match the two NET_ARP_ADDRESSes.
+
+ @param AddressOne Pointer to the first address to match.
+ @param AddressTwo Pointer to the second address to match.
+
+ @return The two addresses match or not.
+
+**/
+STATIC
+BOOLEAN
+ArpMatchAddress (
+ IN NET_ARP_ADDRESS *AddressOne,
+ IN NET_ARP_ADDRESS *AddressTwo
+ )
+{
+ if ((AddressOne->Type != AddressTwo->Type) ||
+ (AddressOne->Length != AddressTwo->Length)) {
+ //
+ // Either Type or Length doesn't match.
+ //
+ return FALSE;
+ }
+
+ if ((AddressOne->AddressPtr != NULL) &&
+ (NetCompareMem (
+ AddressOne->AddressPtr,
+ AddressTwo->AddressPtr,
+ AddressOne->Length
+ ) != 0)) {
+ //
+ // The address is not the same.
+ //
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Find the CacheEntry which matches the requirements in the specified CacheTable.
+
+ @param CacheTable Pointer to the arp cache table.
+ @param StartEntry Pointer to the start entry this search begins with
+ in the cache table.
+ @param FindOpType The search type.
+ @param ProtocolAddress Pointer to the protocol address to match.
+ @param HardwareAddress Pointer to the hardware address to match.
+
+ @return Pointer to the matched arp cache entry, if NULL, no match is found.
+
+**/
+ARP_CACHE_ENTRY *
+ArpFindNextCacheEntryInTable (
+ IN NET_LIST_ENTRY *CacheTable,
+ IN NET_LIST_ENTRY *StartEntry,
+ IN FIND_OPTYPE FindOpType,
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
+ )
+{
+ NET_LIST_ENTRY *Entry;
+ ARP_CACHE_ENTRY *CacheEntry;
+
+ if (StartEntry == NULL) {
+ //
+ // Start from the beginning of the table if no StartEntry is specified.
+ //
+ StartEntry = CacheTable;
+ }
+
+ for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
+
+ if (FindOpType & MATCH_SW_ADDRESS) {
+ //
+ // Find by the software address.
+ //
+ if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) {
+ //
+ // The ProtocolAddress doesn't match, continue to the next cache entry.
+ //
+ continue;
+ }
+ }
+
+ if (FindOpType & MATCH_HW_ADDRESS) {
+ //
+ // Find by the hardware address.
+ //
+ if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) {
+ //
+ // The HardwareAddress doesn't match, continue to the next cache entry.
+ //
+ continue;
+ }
+ }
+
+ //
+ // The CacheEntry meets the requirements now, return this entry.
+ //
+ return CacheEntry;
+ }
+
+ //
+ // No matching.
+ //
+ return NULL;
+}
+
+
+/**
+ Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,
+ in the DeniedCacheTable.
+
+ @param ArpService Pointer to the arp service context data.
+ @param ProtocolAddress Pointer to the protocol address.
+ @param HardwareAddress Pointer to the hardware address.
+
+ @return Pointer to the matched cache entry, if NULL no match is found.
+
+**/
+ARP_CACHE_ENTRY *
+ArpFindDeniedCacheEntry (
+ IN ARP_SERVICE_DATA *ArpService,
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
+ )
+{
+ ARP_CACHE_ENTRY *CacheEntry;
+
+ ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL));
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);
+
+ CacheEntry = NULL;
+
+ if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) {
+ //
+ // Find the cache entry in the DeniedCacheTable by the protocol address.
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->DeniedCacheTable,
+ NULL,
+ ByProtoAddress,
+ ProtocolAddress,
+ NULL
+ );
+ if (CacheEntry != NULL) {
+ //
+ // There is a match.
+ //
+ return CacheEntry;
+ }
+ }
+
+ if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) {
+ //
+ // Find the cache entry in the DeniedCacheTable by the hardware address.
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->DeniedCacheTable,
+ NULL,
+ ByHwAddress,
+ NULL,
+ HardwareAddress
+ );
+ }
+
+ return CacheEntry;
+}
+
+
+/**
+ Allocate a cache entry and initialize it.
+
+ @param Instance Pointer to the instance context data.
+
+ @return Pointer to the new created cache entry.
+
+**/
+ARP_CACHE_ENTRY *
+ArpAllocCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance
+ )
+{
+ ARP_CACHE_ENTRY *CacheEntry;
+ NET_ARP_ADDRESS *Address;
+ UINT16 Index;
+
+ //
+ // Allocate memory for the cache entry.
+ //
+ CacheEntry = NetAllocatePool (sizeof (ARP_CACHE_ENTRY));
+ if (CacheEntry == NULL) {
+ return NULL;
+ }
+
+ //
+ // Init the lists.
+ //
+ NetListInit (&CacheEntry->List);
+ NetListInit (&CacheEntry->UserRequestList);
+
+ for (Index = 0; Index < 2; Index++) {
+ //
+ // Init the address pointers to point to the concrete buffer.
+ //
+ Address = &CacheEntry->Addresses[Index];
+ Address->AddressPtr = Address->Buffer.ProtoAddress;
+ }
+
+ //
+ // Zero the hardware address first.
+ //
+ NetZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN);
+
+ if (Instance != NULL) {
+ //
+ // Inherit the parameters from the instance configuration.
+ //
+ CacheEntry->RetryCount = Instance->ConfigData.RetryCount;
+ CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
+ CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut;
+ CacheEntry->DecayTime = Instance->ConfigData.EntryTimeOut;
+ } else {
+ //
+ // Use the default parameters if this cache entry isn't allocate in a
+ // instance's scope.
+ //
+ CacheEntry->RetryCount = ARP_DEFAULT_RETRY_COUNT;
+ CacheEntry->NextRetryTime = ARP_DEFAULT_RETRY_INTERVAL;
+ CacheEntry->DefaultDecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
+ CacheEntry->DecayTime = ARP_DEFAULT_TIMEOUT_VALUE;
+ }
+
+ return CacheEntry;
+}
+
+
+/**
+ Turn the CacheEntry into the resolved status.
+
+ @param CacheEntry Pointer to the resolved cache entry.
+ @param Instance Pointer to the instance context data.
+ @param UserEvent Pointer to the UserEvent to notify.
+
+ @return The count of notifications sent to the instance.
+
+**/
+UINTN
+ArpAddressResolved (
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN ARP_INSTANCE_DATA *Instance OPTIONAL,
+ IN EFI_EVENT UserEvent OPTIONAL
+ )
+{
+ NET_LIST_ENTRY *Entry;
+ NET_LIST_ENTRY *NextEntry;
+ USER_REQUEST_CONTEXT *Context;
+ UINTN Count;
+
+ Count = 0;
+
+ //
+ // Iterate all the linked user requests to notify them.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) {
+ Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List);
+
+ if (((Instance == NULL) || (Context->Instance == Instance)) &&
+ ((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent))) {
+ //
+ // Copy the address to the user-provided buffer and notify the user.
+ //
+ NetCopyMem (
+ Context->UserHwAddrBuffer,
+ CacheEntry->Addresses[Hardware].AddressPtr,
+ CacheEntry->Addresses[Hardware].Length
+ );
+ gBS->SignalEvent (Context->UserRequestEvent);
+
+ //
+ // Remove this user request and free the context data.
+ //
+ NetListRemoveEntry (&Context->List);
+ NetFreePool (Context);
+
+ Count++;
+ }
+ }
+
+ return Count;
+}
+
+
+/**
+ Fill the addresses in the CacheEntry using the information passed in by
+ HwAddr and SwAddr.
+
+ @param CacheEntry Pointer to the cache entry.
+ @param HwAddr Pointer to the software address.
+ @param SwAddr Pointer to the hardware address.
+
+ @return None.
+
+**/
+VOID
+ArpFillAddressInCacheEntry (
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
+ IN NET_ARP_ADDRESS *SwAddr OPTIONAL
+ )
+{
+ NET_ARP_ADDRESS *Address[2];
+ NET_ARP_ADDRESS *CacheAddress;
+ UINT32 Index;
+
+ Address[Hardware] = HwAddr;
+ Address[Protocol] = SwAddr;
+
+ for (Index = 0; Index < 2; Index++) {
+ if (Address[Index] != NULL) {
+ //
+ // Fill the address if the passed in pointer is not NULL.
+ //
+ CacheAddress = &CacheEntry->Addresses[Index];
+
+ CacheAddress->Type = Address[Index]->Type;
+ CacheAddress->Length = Address[Index]->Length;
+
+ if (Address[Index]->AddressPtr != NULL) {
+ //
+ // Copy it if the AddressPtr points to some buffer.
+ //
+ NetCopyMem (
+ CacheAddress->AddressPtr,
+ Address[Index]->AddressPtr,
+ CacheAddress->Length
+ );
+ } else {
+ //
+ // Zero the corresponding address buffer in the CacheEntry.
+ //
+ NetZeroMem (CacheAddress->AddressPtr, CacheAddress->Length);
+ }
+ }
+ }
+}
+
+
+/**
+ Configure the instance using the ConfigData. ConfigData is already validated.
+
+ @param Instance Pointer to the instance context data to be
+ configured.
+ @param ConfigData Pointer to the configuration data used to
+ configure the instance.
+
+ @retval EFI_SUCCESS The instance is configured with the ConfigData.
+ @retval EFI_ACCESS_DENIED The instance is already configured and the
+ ConfigData tries to reset some unchangeable
+ fields.
+ @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address
+ when the SwAddressType is IPv4.
+ @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory
+ limitation.
+
+**/
+EFI_STATUS
+ArpConfigureInstance (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
+ )
+{
+ EFI_ARP_CONFIG_DATA *OldConfigData;
+ IP4_ADDR Ip;
+
+ OldConfigData = &Instance->ConfigData;
+
+ if (ConfigData != NULL) {
+
+ if (Instance->Configured) {
+ //
+ // The instance is configured, check the unchangeable fields.
+ //
+ if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) ||
+ (OldConfigData->SwAddressLength != ConfigData->SwAddressLength) ||
+ (NetCompareMem (
+ OldConfigData->StationAddress,
+ ConfigData->StationAddress,
+ OldConfigData->SwAddressLength
+ ) != 0)) {
+ //
+ // Deny the unallowed changes.
+ //
+ return EFI_ACCESS_DENIED;
+ }
+ } else {
+ //
+ // The instance is not configured.
+ //
+
+ if (ConfigData->SwAddressType == IPv4_ETHER_PROTO_TYPE) {
+ NetCopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR));
+
+ if (!Ip4IsUnicast (NTOHL (Ip), 0)) {
+ //
+ // The station address is not a valid IPv4 unicast address.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Save the configuration.
+ //
+ CopyMem (OldConfigData, ConfigData, sizeof (EFI_ARP_CONFIG_DATA));
+
+ OldConfigData->StationAddress = NetAllocatePool (OldConfigData->SwAddressLength);
+ if (OldConfigData->StationAddress == NULL) {
+ ARP_DEBUG_ERROR (("ArpConfigInstance: NetAllocatePool for the StationAddress "
+ "failed.\n"));
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Save the StationAddress.
+ //
+ NetCopyMem (
+ OldConfigData->StationAddress,
+ ConfigData->StationAddress,
+ OldConfigData->SwAddressLength
+ );
+
+ //
+ // Set the state to configured.
+ //
+ Instance->Configured = TRUE;
+ }
+
+ //
+ // Use the implementation specific values if the following field is zero.
+ //
+ OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ?
+ ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut;
+
+ OldConfigData->RetryCount = (ConfigData->RetryCount == 0) ?
+ ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount;
+
+ OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ?
+ ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut;
+ } else {
+ //
+ // Reset the configuration.
+ //
+
+ if (Instance->Configured) {
+ //
+ // Cancel the arp requests issued by this instance.
+ //
+ ArpCancelRequest (Instance, NULL, NULL);
+
+ //
+ // Free the buffer previously allocated to hold the station address.
+ //
+ NetFreePool (OldConfigData->StationAddress);
+ }
+
+ Instance->Configured = FALSE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Send out an arp frame using the CachEntry and the ArpOpCode.
+
+ @param Instance Pointer to the instance context data.
+ @param CacheEntry Pointer to the configuration data used to
+ configure the instance.
+ @param ArpOpCode The opcode used to send out this Arp frame, either
+ request or reply.
+
+ @return None.
+
+**/
+VOID
+ArpSendFrame (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN UINT16 ArpOpCode
+ )
+{
+ EFI_STATUS Status;
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;
+ EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;
+ UINT32 TotalLength;
+ UINT8 *Packet;
+ ARP_SERVICE_DATA *ArpService;
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;
+ EFI_ARP_CONFIG_DATA *ConfigData;
+ UINT8 *TmpPtr;
+ ARP_HEAD *ArpHead;
+
+ ASSERT ((Instance != NULL) && (CacheEntry != NULL));
+
+ //
+ // Allocate memory for the TxToken.
+ //
+ TxToken = NetAllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN));
+ if (TxToken == NULL) {
+ ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for TxToken failed.\n"));
+ return;
+ }
+
+ TxToken->Event = NULL;
+ TxData = NULL;
+ Packet = NULL;
+
+ //
+ // Create the event for this TxToken.
+ //
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ NET_TPL_EVENT,
+ ArpOnFrameSent,
+ (VOID *)TxToken,
+ &TxToken->Event
+ );
+ if (EFI_ERROR (Status)) {
+ ARP_DEBUG_ERROR (("ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));
+ goto CLEAN_EXIT;
+ }
+
+ //
+ // Allocate memory for the TxData used in the TxToken.
+ //
+ TxData = NetAllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA));
+ if (TxData == NULL) {
+ ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for TxData failed.\n"));
+ goto CLEAN_EXIT;
+ }
+
+ ArpService = Instance->ArpService;
+ SnpMode = &ArpService->SnpMode;
+ ConfigData = &Instance->ConfigData;
+
+ //
+ // Calculate the buffer length for this arp frame.
+ //
+ TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) +
+ 2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize);
+
+ //
+ // Allocate buffer for the arp frame.
+ //
+ Packet = NetAllocatePool (TotalLength);
+ if (Packet == NULL) {
+ ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for Packet failed.\n"));
+ }
+
+ TmpPtr = Packet;
+
+ //
+ // The destination MAC address.
+ //
+ if (ArpOpCode == ARP_OPCODE_REQUEST) {
+ NetCopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
+ } else {
+ NetCopyMem (
+ TmpPtr,
+ CacheEntry->Addresses[Hardware].AddressPtr,
+ SnpMode->HwAddressSize
+ );
+ }
+ TmpPtr += SnpMode->HwAddressSize;
+
+ //
+ // The source MAC address.
+ //
+ NetCopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
+ TmpPtr += SnpMode->HwAddressSize;
+
+ //
+ // The ethernet protocol type.
+ //
+ *(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE);
+ TmpPtr += 2;
+
+ //
+ // The ARP Head.
+ //
+ ArpHead = (ARP_HEAD *) TmpPtr;
+ ArpHead->HwType = HTONS ((UINT16)SnpMode->IfType);
+ ArpHead->ProtoType = HTONS (ConfigData->SwAddressType);
+ ArpHead->HwAddrLen = (UINT8)SnpMode->HwAddressSize;
+ ArpHead->ProtoAddrLen = ConfigData->SwAddressLength;
+ ArpHead->OpCode = HTONS (ArpOpCode);
+ TmpPtr += sizeof (ARP_HEAD);
+
+ //
+ // The sender hardware address.
+ //
+ NetCopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);
+ TmpPtr += SnpMode->HwAddressSize;
+
+ //
+ // The sender protocol address.
+ //
+ NetCopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength);
+ TmpPtr += ConfigData->SwAddressLength;
+
+ //
+ // The target hardware address.
+ //
+ NetCopyMem (
+ TmpPtr,
+ CacheEntry->Addresses[Hardware].AddressPtr,
+ SnpMode->HwAddressSize
+ );
+ TmpPtr += SnpMode->HwAddressSize;
+
+ //
+ // The target protocol address.
+ //
+ NetCopyMem (
+ TmpPtr,
+ CacheEntry->Addresses[Protocol].AddressPtr,
+ ConfigData->SwAddressLength
+ );
+
+ //
+ // Set all the fields of the TxData.
+ //
+ TxData->DestinationAddress = NULL;
+ TxData->SourceAddress = NULL;
+ TxData->ProtocolType = 0;
+ TxData->DataLength = TotalLength - SnpMode->MediaHeaderSize;
+ TxData->HeaderLength = (UINT16) SnpMode->MediaHeaderSize;
+ TxData->FragmentCount = 1;
+
+ TxData->FragmentTable[0].FragmentBuffer = Packet;
+ TxData->FragmentTable[0].FragmentLength = TotalLength;
+
+ //
+ // Associate the TxData with the TxToken.
+ //
+ TxToken->Packet.TxData = TxData;
+ TxToken->Status = EFI_NOT_READY;
+
+ //
+ // Send out this arp packet by Mnp.
+ //
+ Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken);
+ if (EFI_ERROR (Status)) {
+ ARP_DEBUG_ERROR (("Mnp->Transmit failed, %r.\n", Status));
+ goto CLEAN_EXIT;
+ }
+
+ return;
+
+CLEAN_EXIT:
+
+ if (Packet != NULL) {
+ NetFreePool (Packet);
+ }
+
+ if (TxData != NULL) {
+ NetFreePool (TxData);
+ }
+
+ if (TxToken->Event != NULL) {
+ gBS->CloseEvent (TxToken->Event);
+ }
+
+ NetFreePool (TxToken);
+}
+
+
+/**
+ Delete the cache entries in the specified CacheTable, using the BySwAddress,
+ SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,
+ the cache is deleted event it's a static entry.
+
+ @param CacheTable Pointer to the cache table to do the deletion.
+ @param BySwAddress Delete the cache entry by software address or by
+ hardware address.
+ @param SwAddressType The software address used to do the deletion.
+ @param AddressBuffer Pointer to the buffer containing the address to
+ match for the deletion.
+ @param Force This deletion is forced or not.
+
+ @return The count of the deleted cache entries.
+
+**/
+STATIC
+UINTN
+ArpDeleteCacheEntryInTable (
+ IN NET_LIST_ENTRY *CacheTable,
+ IN BOOLEAN BySwAddress,
+ IN UINT16 SwAddressType,
+ IN UINT8 *AddressBuffer OPTIONAL,
+ IN BOOLEAN Force
+ )
+{
+ NET_LIST_ENTRY *Entry;
+ NET_LIST_ENTRY *NextEntry;
+ ARP_CACHE_ENTRY *CacheEntry;
+ UINTN Count;
+
+ Count = 0;
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) {
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
+
+ if ((CacheEntry->DefaultDecayTime == 0) && !Force) {
+ //
+ // It's a static entry and we are not forced to delete it, skip.
+ //
+ continue;
+ }
+
+ if (BySwAddress) {
+ if (SwAddressType == CacheEntry->Addresses[Protocol].Type) {
+ //
+ // Protocol address type matched. Check the address.
+ //
+ if ((AddressBuffer == NULL) ||
+ (NetCompareMem (
+ AddressBuffer,
+ CacheEntry->Addresses[Protocol].AddressPtr,
+ CacheEntry->Addresses[Protocol].Length
+ ) == 0)) {
+ //
+ // Address matched.
+ //
+ goto MATCHED;
+ }
+ }
+ } else {
+ if ((AddressBuffer == NULL) ||
+ (NetCompareMem (
+ AddressBuffer,
+ CacheEntry->Addresses[Hardware].AddressPtr,
+ CacheEntry->Addresses[Hardware].Length
+ ) == 0)) {
+ //
+ // Address matched.
+ //
+ goto MATCHED;
+ }
+ }
+
+ continue;
+
+MATCHED:
+
+ //
+ // Delete this entry.
+ //
+ NetListRemoveEntry (&CacheEntry->List);
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));
+ NetFreePool (CacheEntry);
+
+ Count++;
+ }
+
+ return Count;
+}
+
+
+/**
+ Delete cache entries in all the cache tables.
+
+ @param Instance Pointer to the instance context data.
+ @param BySwAddress Delete the cache entry by software address or by
+ hardware address.
+ @param AddressBuffer Pointer to the buffer containing the address to
+ match for the deletion.
+ @param Force This deletion is forced or not.
+
+ @return The count of the deleted cache entries.
+
+**/
+UINTN
+ArpDeleteCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN BOOLEAN BySwAddress,
+ IN UINT8 *AddressBuffer OPTIONAL,
+ IN BOOLEAN Force
+ )
+{
+ ARP_SERVICE_DATA *ArpService;
+ UINTN Count;
+
+ NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
+
+ ArpService = Instance->ArpService;
+
+ //
+ // Delete the cache entries in the DeniedCacheTable.
+ //
+ Count = ArpDeleteCacheEntryInTable (
+ &ArpService->DeniedCacheTable,
+ BySwAddress,
+ Instance->ConfigData.SwAddressType,
+ AddressBuffer,
+ Force
+ );
+
+ //
+ // Delete the cache entries inthe ResolvedCacheTable.
+ //
+ Count += ArpDeleteCacheEntryInTable (
+ &ArpService->ResolvedCacheTable,
+ BySwAddress,
+ Instance->ConfigData.SwAddressType,
+ AddressBuffer,
+ Force
+ );
+
+ return Count;
+}
+
+
+/**
+ Cancel the arp request.
+
+ @param Instance Pointer to the instance context data.
+ @param TargetSwAddress Pointer to the buffer containing the target
+ software address to match the arp request.
+ @param UserEvent The user event used to notify this request
+ cancellation.
+
+ @return The count of the cancelled requests.
+
+**/
+UINTN
+ArpCancelRequest (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT UserEvent OPTIONAL
+ )
+{
+ ARP_SERVICE_DATA *ArpService;
+ NET_LIST_ENTRY *Entry;
+ NET_LIST_ENTRY *NextEntry;
+ ARP_CACHE_ENTRY *CacheEntry;
+ UINTN Count;
+
+ NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);
+
+ ArpService = Instance->ArpService;
+
+ Count = 0;
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);
+
+ if ((TargetSwAddress == NULL) ||
+ (NetCompareMem (
+ TargetSwAddress,
+ CacheEntry->Addresses[Protocol].AddressPtr,
+ CacheEntry->Addresses[Protocol].Length
+ ) == 0)) {
+ //
+ // This request entry matches the TargetSwAddress or all requests are to be
+ // cancelled as TargetSwAddress is NULL.
+ //
+ Count += ArpAddressResolved (CacheEntry, Instance, UserEvent);
+
+ if (NetListIsEmpty (&CacheEntry->UserRequestList)) {
+ //
+ // No user requests any more, remove this request cache entry.
+ //
+ NetListRemoveEntry (&CacheEntry->List);
+ NetFreePool (CacheEntry);
+ }
+ }
+ }
+
+ return Count;
+}
+
+
+/**
+ Find the cache entry in the cache table.
+
+ @param Instance Pointer to the instance context data.
+ @param BySwAddress Set to TRUE to look for matching software protocol
+ addresses. Set to FALSE to look for matching
+ hardware protocol addresses.
+ @param AddressBuffer Pointer to address buffer. Set to NULL to match
+ all addresses.
+ @param EntryLength The size of an entry in the entries buffer.
+ @param EntryCount The number of ARP cache entries that are found by
+ the specified criteria.
+ @param Entries Pointer to the buffer that will receive the ARP
+ cache entries.
+ @param Refresh Set to TRUE to refresh the timeout value of the
+ matching ARP cache entry.
+
+ @retval EFI_SUCCESS The requested ARP cache entries are copied into
+ the buffer.
+ @retval EFI_NOT_FOUND No matching entries found.
+ @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.
+
+**/
+EFI_STATUS
+ArpFindCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL,
+ OUT UINT32 *EntryLength OPTIONAL,
+ OUT UINT32 *EntryCount OPTIONAL,
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
+ IN BOOLEAN Refresh
+ )
+{
+ EFI_STATUS Status;
+ ARP_SERVICE_DATA *ArpService;
+ NET_ARP_ADDRESS MatchAddress;
+ FIND_OPTYPE FindOpType;
+ NET_LIST_ENTRY *StartEntry;
+ ARP_CACHE_ENTRY *CacheEntry;
+ NET_MAP FoundEntries;
+ UINT32 FoundCount;
+ EFI_ARP_FIND_DATA *FindData;
+ NET_LIST_ENTRY *CacheTable;
+
+ ArpService = Instance->ArpService;
+
+ //
+ // Init the FounEntries used to hold the found cache entries.
+ //
+ NetMapInit (&FoundEntries);
+
+ //
+ // Set the MatchAddress.
+ //
+ if (BySwAddress) {
+ MatchAddress.Type = Instance->ConfigData.SwAddressType;
+ MatchAddress.Length = Instance->ConfigData.SwAddressLength;
+ FindOpType = ByProtoAddress;
+ } else {
+ MatchAddress.Type = ArpService->SnpMode.IfType;
+ MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize;
+ FindOpType = ByHwAddress;
+ }
+
+ MatchAddress.AddressPtr = AddressBuffer;
+
+ //
+ // Search the DeniedCacheTable
+ //
+ StartEntry = NULL;
+ while (TRUE) {
+ //
+ // Try to find the matched entries in the DeniedCacheTable.
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->DeniedCacheTable,
+ StartEntry,
+ FindOpType,
+ &MatchAddress,
+ &MatchAddress
+ );
+ if (CacheEntry == NULL) {
+ //
+ // Once the CacheEntry is NULL, there are no more matches.
+ //
+ break;
+ }
+
+ //
+ // Insert the found entry into the map.
+ //
+ NetMapInsertTail (
+ &FoundEntries,
+ (VOID *)CacheEntry,
+ (VOID *)&ArpService->DeniedCacheTable
+ );
+
+ //
+ // Let the next search start from this cache entry.
+ //
+ StartEntry = &CacheEntry->List;
+
+ if (Refresh) {
+ //
+ // Refresh the DecayTime if needed.
+ //
+ CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
+ }
+ }
+
+ //
+ // Search the ResolvedCacheTable
+ //
+ StartEntry = NULL;
+ while (TRUE) {
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->ResolvedCacheTable,
+ StartEntry,
+ FindOpType,
+ &MatchAddress,
+ &MatchAddress
+ );
+ if (CacheEntry == NULL) {
+ //
+ // Once the CacheEntry is NULL, there are no more matches.
+ //
+ break;
+ }
+
+ //
+ // Insert the found entry into the map.
+ //
+ NetMapInsertTail (
+ &FoundEntries,
+ (VOID *)CacheEntry,
+ (VOID *)&ArpService->ResolvedCacheTable
+ );
+
+ //
+ // Let the next search start from this cache entry.
+ //
+ StartEntry = &CacheEntry->List;
+
+ if (Refresh) {
+ //
+ // Refresh the DecayTime if needed.
+ //
+ CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;
+ }
+ }
+
+ Status = EFI_SUCCESS;
+
+ FoundCount = (UINT32) NetMapGetCount (&FoundEntries);
+ if (FoundCount == 0) {
+ Status = EFI_NOT_FOUND;
+ goto CLEAN_EXIT;
+ }
+
+ if (EntryLength != NULL) {
+ //
+ // Return the entry length.
+ //
+ *EntryLength = sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +
+ ArpService->SnpMode.HwAddressSize;
+ }
+
+ if (EntryCount != NULL) {
+ //
+ // Return the found entry count.
+ //
+ *EntryCount = FoundCount;
+ }
+
+ if (Entries == NULL) {
+ goto CLEAN_EXIT;
+ }
+
+ //
+ // Allocate buffer to copy the found entries.
+ //
+ FindData = NetAllocatePool (FoundCount * (*EntryLength));
+ if (FindData == NULL) {
+ ARP_DEBUG_ERROR (("ArpFindCacheEntry: Failed to allocate memory.\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto CLEAN_EXIT;
+ }
+
+ //
+ // Return the address to the user.
+ //
+ *Entries = FindData;
+
+ //
+ // Dump the entries.
+ //
+ while (!NetMapIsEmpty (&FoundEntries)) {
+ //
+ // Get a cache entry from the map.
+ //
+ CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable);
+
+ //
+ // Set the fields in FindData.
+ //
+ FindData->Size = *EntryLength;
+ FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);
+ FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);
+ FindData->HwAddressType = ArpService->SnpMode.IfType;
+ FindData->SwAddressType = Instance->ConfigData.SwAddressType;
+ FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize;
+ FindData->SwAddressLength = Instance->ConfigData.SwAddressLength;
+
+ //
+ // Copy the software address.
+ //
+ NetCopyMem (
+ FindData + 1,
+ CacheEntry->Addresses[Protocol].AddressPtr,
+ FindData->SwAddressLength
+ );
+
+ //
+ // Copy the hardware address.
+ //
+ NetCopyMem (
+ (UINT8 *)(FindData + 1) + FindData->SwAddressLength,
+ CacheEntry->Addresses[Hardware].AddressPtr,
+ FindData->HwAddressLength
+ );
+
+ //
+ // Slip to the next FindData.
+ //
+ FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + *EntryLength);
+ }
+
+CLEAN_EXIT:
+
+ NetMapClean (&FoundEntries);
+
+ return Status;
+}
+
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.h b/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.h
new file mode 100644
index 0000000..607443a
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpImpl.h
@@ -0,0 +1,341 @@
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpImpl.h
+
+Abstract:
+
+
+**/
+
+#ifndef _ARP_IMPL_H_
+#define _ARP_IMPL_H_
+
+
+#include <PiDxe.h>
+
+#include <Protocol/Arp.h>
+#include <Protocol/ManagedNetwork.h>
+#include <Protocol/ServiceBinding.h>
+
+#include <Library/DebugLib.h>
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+#include <Library/NetLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "ArpDebug.h"
+
+#define ARP_ETHER_PROTO_TYPE 0x0806
+#define IPv4_ETHER_PROTO_TYPE 0x0800
+#define IPv6_ETHER_PROTO_TYPE 0x86DD
+
+#define ARP_OPCODE_REQUEST 0x0001
+#define ARP_OPCODE_REPLY 0x0002
+
+#define ARP_DEFAULT_TIMEOUT_VALUE (400 * TICKS_PER_SECOND)
+#define ARP_DEFAULT_RETRY_COUNT 2
+#define ARP_DEFAULT_RETRY_INTERVAL (5 * TICKS_PER_MS)
+#define ARP_PERIODIC_TIMER_INTERVAL (500 * TICKS_PER_MS)
+
+#pragma pack(1)
+typedef struct _ARP_HEAD {
+ UINT16 HwType;
+ UINT16 ProtoType;
+ UINT8 HwAddrLen;
+ UINT8 ProtoAddrLen;
+ UINT16 OpCode;
+} ARP_HEAD;
+#pragma pack()
+
+typedef struct _ARP_ADDRESS {
+ UINT8 *SenderHwAddr;
+ UINT8 *SenderProtoAddr;
+ UINT8 *TargetHwAddr;
+ UINT8 *TargetProtoAddr;
+} ARP_ADDRESS;
+
+#define MATCH_SW_ADDRESS 0x1
+#define MATCH_HW_ADDRESS 0x2
+
+typedef enum {
+ ByNone = 0,
+ ByProtoAddress = MATCH_SW_ADDRESS,
+ ByHwAddress = MATCH_HW_ADDRESS,
+ ByBoth = MATCH_SW_ADDRESS | MATCH_HW_ADDRESS
+} FIND_OPTYPE;
+
+#define ARP_INSTANCE_DATA_SIGNATURE EFI_SIGNATURE_32('A', 'R', 'P', 'I')
+
+#define ARP_INSTANCE_DATA_FROM_THIS(a) \
+ CR ( \
+ (a), \
+ ARP_INSTANCE_DATA, \
+ ArpProto, \
+ ARP_INSTANCE_DATA_SIGNATURE \
+ )
+
+typedef struct _ARP_SERVICE_DATA ARP_SERVICE_DATA;
+
+typedef struct _ARP_INSTANCE_DATA {
+ UINT32 Signature;
+ ARP_SERVICE_DATA *ArpService;
+ EFI_HANDLE Handle;
+ EFI_ARP_PROTOCOL ArpProto;
+ NET_LIST_ENTRY List;
+ EFI_ARP_CONFIG_DATA ConfigData;
+ BOOLEAN Configured;
+ BOOLEAN Destroyed;
+} ARP_INSTANCE_DATA;
+
+#define ARP_SERVICE_DATA_SIGNATURE EFI_SIGNATURE_32('A', 'R', 'P', 'S')
+
+#define ARP_SERVICE_DATA_FROM_THIS(a) \
+ CR ( \
+ (a), \
+ ARP_SERVICE_DATA, \
+ ServiceBinding, \
+ ARP_SERVICE_DATA_SIGNATURE \
+ )
+
+struct _ARP_SERVICE_DATA {
+ UINT32 Signature;
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
+
+ EFI_HANDLE MnpChildHandle;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE ControllerHandle;
+
+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
+ EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN RxToken;
+
+ EFI_SIMPLE_NETWORK_MODE SnpMode;
+
+ NET_LOCK Lock;
+
+ UINTN ChildrenNumber;
+ NET_LIST_ENTRY ChildrenList;
+
+ NET_LIST_ENTRY PendingRequestTable;
+ NET_LIST_ENTRY DeniedCacheTable;
+ NET_LIST_ENTRY ResolvedCacheTable;
+
+ EFI_EVENT PeriodicTimer;
+};
+
+typedef struct _USER_REQUEST_CONTEXT {
+ NET_LIST_ENTRY List;
+ ARP_INSTANCE_DATA *Instance;
+ EFI_EVENT UserRequestEvent;
+ VOID *UserHwAddrBuffer;
+} USER_REQUEST_CONTEXT;
+
+#define ARP_MAX_PROTOCOL_ADDRESS_LEN sizeof(EFI_IP_ADDRESS)
+#define ARP_MAX_HARDWARE_ADDRESS_LEN sizeof(EFI_MAC_ADDRESS)
+
+typedef struct _NET_ARP_ADDRESS {
+ UINT16 Type;
+ UINT8 Length;
+ UINT8 *AddressPtr;
+ union {
+ UINT8 ProtoAddress[ARP_MAX_PROTOCOL_ADDRESS_LEN];
+ UINT8 HwAddress[ARP_MAX_HARDWARE_ADDRESS_LEN];
+ } Buffer;
+} NET_ARP_ADDRESS;
+
+typedef enum {
+ Hardware,
+ Protocol
+} ARP_ADDRESS_TYPE;
+
+typedef struct _ARP_CACHE_ENTRY {
+ NET_LIST_ENTRY List;
+
+ UINT32 RetryCount;
+ UINT32 DefaultDecayTime;
+ UINT32 DecayTime;
+ UINT32 NextRetryTime;
+
+ NET_ARP_ADDRESS Addresses[2];
+
+ NET_LIST_ENTRY UserRequestList;
+} ARP_CACHE_ENTRY;
+
+EFI_STATUS
+EFIAPI
+ArpConfigure (
+ IN EFI_ARP_PROTOCOL *This,
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpAdd (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN DenyFlag,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN VOID *TargetHwAddress OPTIONAL,
+ IN UINT32 TimeoutValue,
+ IN BOOLEAN Overwrite
+ );
+
+EFI_STATUS
+EFIAPI
+ArpFind (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL,
+ OUT UINT32 *EntryLength OPTIONAL,
+ OUT UINT32 *EntryCount OPTIONAL,
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
+ IN BOOLEAN Refresh
+ );
+
+EFI_STATUS
+EFIAPI
+ArpDelete (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpFlush (
+ IN EFI_ARP_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+ArpRequest (
+ IN EFI_ARP_PROTOCOL *This,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT ResolvedEvent OPTIONAL,
+ OUT VOID *TargetHwAddress
+ );
+
+EFI_STATUS
+EFIAPI
+ArpCancel (
+ IN EFI_ARP_PROTOCOL *This,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT ResolvedEvent OPTIONAL
+ );
+
+EFI_STATUS
+ArpConfigureInstance (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
+ );
+
+ARP_CACHE_ENTRY *
+ArpFindDeniedCacheEntry (
+ IN ARP_SERVICE_DATA *ArpService,
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
+ );
+
+ARP_CACHE_ENTRY *
+ArpFindNextCacheEntryInTable (
+ IN NET_LIST_ENTRY *CacheTable,
+ IN NET_LIST_ENTRY *StartEntry,
+ IN FIND_OPTYPE FindOpType,
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
+ );
+
+ARP_CACHE_ENTRY *
+ArpAllocCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance
+ );
+
+VOID
+ArpFillAddressInCacheEntry (
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
+ IN NET_ARP_ADDRESS *SwAddr OPTIONAL
+ );
+
+UINTN
+ArpAddressResolved (
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN ARP_INSTANCE_DATA *Instance OPTIONAL,
+ IN EFI_EVENT UserEvent OPTIONAL
+ );
+
+UINTN
+ArpDeleteCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN BOOLEAN BySwAddress,
+ IN UINT8 *AddressBuffer OPTIONAL,
+ IN BOOLEAN Force
+ );
+
+VOID
+ArpSendFrame (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN UINT16 ArpOpCode
+ );
+
+VOID
+ArpInitInstance (
+ IN ARP_SERVICE_DATA *ArpService,
+ IN ARP_INSTANCE_DATA *Instance
+ );
+
+VOID
+EFIAPI
+ArpOnFrameRcvd (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+EFIAPI
+ArpOnFrameSent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+EFIAPI
+ArpTimerHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+UINTN
+ArpCancelRequest (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT UserEvent OPTIONAL
+ );
+
+EFI_STATUS
+ArpFindCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL,
+ OUT UINT32 *EntryLength OPTIONAL,
+ OUT UINT32 *EntryCount OPTIONAL,
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
+ IN BOOLEAN Refresh
+ );
+
+#endif
+
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ArpMain.c b/MdeModulePkg/Universal/Network/ArpDxe/ArpMain.c
new file mode 100644
index 0000000..eb1b082
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ArpMain.c
@@ -0,0 +1,727 @@
+/** @file
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpMain.c
+
+Abstract:
+
+
+**/
+
+#include "ArpImpl.h"
+
+
+/**
+ This function is used to assign a station address to the ARP cache for this instance
+ of the ARP driver. A call to this function with the ConfigData field set to NULL
+ will reset this ARP instance.
+
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.
+ @param ConfigData Pointer to the EFI_ARP_CONFIG_DATA structure.
+
+ @retval EFI_SUCCESS The new station address was successfully
+ registered.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL. SwAddressLength is zero when
+ ConfigData is not NULL. StationAddress is NULL
+ when ConfigData is not NULL.
+ @retval EFI_ACCESS_DENIED The SwAddressType, SwAddressLength, or
+ StationAddress is different from the one that is
+ already registered.
+ @retval EFI_OUT_OF_RESOURCES Storage for the new StationAddress could not be
+ allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpConfigure (
+ IN EFI_ARP_PROTOCOL *This,
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ ARP_INSTANCE_DATA *Instance;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((ConfigData != NULL) &&
+ ((ConfigData->SwAddressLength == 0) ||
+ (ConfigData->StationAddress == NULL) ||
+ (ConfigData->SwAddressType <= 1500))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
+
+ if (EFI_ERROR (NET_TRYLOCK (&Instance->ArpService->Lock))) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Configure this instance, the ConfigData has already passed the basic checks.
+ //
+ Status = ArpConfigureInstance (Instance, ConfigData);
+
+ NET_UNLOCK (&Instance->ArpService->Lock);
+
+ return Status;
+}
+
+
+/**
+ This function is used to insert entries into the ARP cache.
+
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.
+ @param DenyFlag Set to TRUE if this entry is a deny entry. Set to
+ FALSE if this entry is a normal entry.
+ @param TargetSwAddress Pointer to a protocol address to add (or deny).
+ May be set to NULL if DenyFlag is TRUE.
+ @param TargetHwAddress Pointer to a hardware address to add (or deny).
+ May be set to NULL if DenyFlag is TRUE.
+ @param TimeoutValue Time in 100-ns units that this entry will remain
+ in the ARP cache. A value of zero means that the
+ entry is permanent. A nonzero value will override
+ the one given by Configure() if the entry to be
+ added is a dynamic entry.
+ @param Overwrite If TRUE, the matching cache entry will be
+ overwritten with the supplied parameters. If
+ FALSE, EFI_ACCESS_DENIED is returned if the
+ corresponding cache entry already exists.
+
+ @retval EFI_SUCCESS The entry has been added or updated.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL. DenyFlag is FALSE and
+ TargetHwAddress is NULL. DenyFlag is FALSE and
+ TargetSwAddress is NULL. TargetHwAddress is NULL
+ and TargetSwAddress is NULL. Both TargetSwAddress
+ and TargetHwAddress are not NULL when DenyFlag is
+ TRUE.
+ @retval EFI_OUT_OF_RESOURCES The new ARP cache entry could not be allocated.
+ @retval EFI_ACCESS_DENIED The ARP cache entry already exists and Overwrite
+ is not true.
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpAdd (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN DenyFlag,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN VOID *TargetHwAddress OPTIONAL,
+ IN UINT32 TimeoutValue,
+ IN BOOLEAN Overwrite
+ )
+{
+ EFI_STATUS Status;
+ ARP_INSTANCE_DATA *Instance;
+ ARP_SERVICE_DATA *ArpService;
+ ARP_CACHE_ENTRY *CacheEntry;
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;
+ NET_ARP_ADDRESS MatchAddress[2];
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (((!DenyFlag) && ((TargetHwAddress == NULL) || (TargetSwAddress == NULL))) ||
+ (DenyFlag && (TargetHwAddress != NULL) && (TargetSwAddress != NULL)) ||
+ ((TargetHwAddress == NULL) && (TargetSwAddress == NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
+
+ if (!Instance->Configured) {
+ return EFI_NOT_STARTED;
+ }
+
+ Status = EFI_SUCCESS;
+ ArpService = Instance->ArpService;
+ SnpMode = &Instance->ArpService->SnpMode;
+
+ //
+ // Fill the hardware address part in the MatchAddress.
+ //
+ MatchAddress[Hardware].Type = SnpMode->IfType;
+ MatchAddress[Hardware].Length = (UINT8) SnpMode->HwAddressSize;
+ MatchAddress[Hardware].AddressPtr = TargetHwAddress;
+
+ //
+ // Fill the software address part in the MatchAddress.
+ //
+ MatchAddress[Protocol].Type = Instance->ConfigData.SwAddressType;
+ MatchAddress[Protocol].Length = Instance->ConfigData.SwAddressLength;
+ MatchAddress[Protocol].AddressPtr = TargetSwAddress;
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // See whether the entry to add exists. Check the DeinedCacheTable first.
+ //
+ CacheEntry = ArpFindDeniedCacheEntry (
+ ArpService,
+ &MatchAddress[Protocol],
+ &MatchAddress[Hardware]
+ );
+
+ if (CacheEntry == NULL) {
+ //
+ // Check the ResolvedCacheTable
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->ResolvedCacheTable,
+ NULL,
+ ByBoth,
+ &MatchAddress[Protocol],
+ &MatchAddress[Hardware]
+ );
+ }
+
+ if ((CacheEntry != NULL) && !Overwrite) {
+ //
+ // The entry to add exists, if not Overwirte, deny this add request.
+ //
+ Status = EFI_ACCESS_DENIED;
+ goto UNLOCK_EXIT;
+ }
+
+ if ((CacheEntry == NULL) && (TargetSwAddress != NULL)) {
+ //
+ // Check whether there are pending requests matching the entry to be added.
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->PendingRequestTable,
+ NULL,
+ ByProtoAddress,
+ &MatchAddress[Protocol],
+ NULL
+ );
+ }
+
+ if (CacheEntry != NULL) {
+ //
+ // Remove it from the Table.
+ //
+ NetListRemoveEntry (&CacheEntry->List);
+ } else {
+ //
+ // It's a new entry, allocate memory for the entry.
+ //
+ CacheEntry = ArpAllocCacheEntry (Instance);
+
+ if (CacheEntry == NULL) {
+ ARP_DEBUG_ERROR (("ArpAdd: Failed to allocate pool for CacheEntry.\n"));
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNLOCK_EXIT;
+ }
+ }
+
+ //
+ // Overwrite these parameters.
+ //
+ CacheEntry->DefaultDecayTime = TimeoutValue;
+ CacheEntry->DecayTime = TimeoutValue;
+
+ //
+ // Fill in the addresses.
+ //
+ ArpFillAddressInCacheEntry (
+ CacheEntry,
+ &MatchAddress[Hardware],
+ &MatchAddress[Protocol]
+ );
+
+ //
+ // Inform the user if there is any.
+ //
+ ArpAddressResolved (CacheEntry, NULL, NULL);
+
+ //
+ // Add this CacheEntry to the corresponding CacheTable.
+ //
+ if (DenyFlag) {
+ NetListInsertHead (&ArpService->DeniedCacheTable, &CacheEntry->List);
+ } else {
+ NetListInsertHead (&ArpService->ResolvedCacheTable, &CacheEntry->List);
+ }
+
+UNLOCK_EXIT:
+
+ NET_UNLOCK (&ArpService->Lock);
+
+ return Status;
+}
+
+
+/**
+ This function searches the ARP cache for matching entries and allocates a buffer into
+ which those entries are copied.
+
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.
+ @param BySwAddress Set to TRUE to look for matching software protocol
+ addresses. Set to FALSE to look for matching
+ hardware protocol addresses.
+ @param AddressBuffer Pointer to address buffer. Set to NULL to match
+ all addresses.
+ @param EntryLength The size of an entry in the entries buffer.
+ @param EntryCount The number of ARP cache entries that are found by
+ the specified criteria.
+ @param Entries Pointer to the buffer that will receive the ARP
+ cache entries.
+ @param Refresh Set to TRUE to refresh the timeout value of the
+ matching ARP cache entry.
+
+ @retval EFI_SUCCESS The requested ARP cache entries were copied into
+ the buffer.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL. Both EntryCount and EntryLength are
+ NULL, when Refresh is FALSE.
+ @retval EFI_NOT_FOUND No matching entries were found.
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpFind (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL,
+ OUT UINT32 *EntryLength OPTIONAL,
+ OUT UINT32 *EntryCount OPTIONAL,
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
+ IN BOOLEAN Refresh
+ )
+{
+ EFI_STATUS Status;
+ ARP_INSTANCE_DATA *Instance;
+ ARP_SERVICE_DATA *ArpService;
+
+ if ((This == NULL) ||
+ (!Refresh && (EntryCount == NULL) && (EntryLength == NULL)) ||
+ ((Entries != NULL) && ((EntryLength == NULL) || (EntryCount == NULL)))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
+ ArpService = Instance->ArpService;
+
+ if (!Instance->Configured) {
+ return EFI_NOT_STARTED;
+ }
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // All the check passed, find the cache entries now.
+ //
+ Status = ArpFindCacheEntry (
+ Instance,
+ BySwAddress,
+ AddressBuffer,
+ EntryLength,
+ EntryCount,
+ Entries,
+ Refresh
+ );
+
+ NET_UNLOCK (&ArpService->Lock);
+
+ return Status;
+}
+
+
+/**
+ This function removes specified ARP cache entries.
+
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.
+ @param BySwAddress Set to TRUE to delete matching protocol addresses.
+ Set to FALSE to delete matching hardware
+ addresses.
+ @param AddressBuffer Pointer to the address buffer that is used as a
+ key to look for the cache entry. Set to NULL to
+ delete all entries.
+
+ @retval EFI_SUCCESS The entry was removed from the ARP cache.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_FOUND The specified deletion key was not found.
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpDelete (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL
+ )
+{
+ ARP_INSTANCE_DATA *Instance;
+ ARP_SERVICE_DATA *ArpService;
+ UINTN Count;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
+
+ if (!Instance->Configured) {
+ return EFI_NOT_STARTED;
+ }
+
+ ArpService = Instance->ArpService;
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Delete the specified cache entries.
+ //
+ Count = ArpDeleteCacheEntry (Instance, BySwAddress, AddressBuffer, TRUE);
+
+ NET_UNLOCK (&ArpService->Lock);
+
+ return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
+
+
+/**
+ This function delete all dynamic entries from the ARP cache that match the specified
+ software protocol type.
+
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.
+
+ @retval EFI_SUCCESS The cache has been flushed.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_NOT_FOUND There are no matching dynamic cache entries.
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpFlush (
+ IN EFI_ARP_PROTOCOL *This
+ )
+{
+ ARP_INSTANCE_DATA *Instance;
+ ARP_SERVICE_DATA *ArpService;
+ UINTN Count;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
+
+ if (!Instance->Configured) {
+ return EFI_NOT_STARTED;
+ }
+
+ ArpService = Instance->ArpService;
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Delete the dynamic entries from the cache table.
+ //
+ Count = ArpDeleteCacheEntry (Instance, FALSE, NULL, FALSE);
+
+ NET_UNLOCK (&ArpService->Lock);
+
+ return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
+
+
+/**
+ This function tries to resolve the TargetSwAddress and optionally returns a
+ TargetHwAddress if it already exists in the ARP cache.
+
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.
+ @param TargetSwAddress Pointer to the protocol address to resolve.
+ @param ResolvedEvent Pointer to the event that will be signaled when
+ the address is resolved or some error occurs.
+ @param TargetHwAddress Pointer to the buffer for the resolved hardware
+ address in network byte order.
+
+ @retval EFI_SUCCESS The data is copied from the ARP cache into the
+ TargetHwAddress buffer.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL. TargetHwAddress is NULL.
+ @retval EFI_ACCESS_DENIED The requested address is not present in the normal
+ ARP cache but is present in the deny address list.
+ Outgoing traffic to that address is forbidden.
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.
+ @retval EFI_NOT_READY The request has been started and is not finished.
+
+**/
+EFI_STATUS
+EFIAPI
+ArpRequest (
+ IN EFI_ARP_PROTOCOL *This,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT ResolvedEvent OPTIONAL,
+ OUT VOID *TargetHwAddress
+ )
+{
+ EFI_STATUS Status;
+ ARP_INSTANCE_DATA *Instance;
+ ARP_SERVICE_DATA *ArpService;
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;
+ ARP_CACHE_ENTRY *CacheEntry;
+ NET_ARP_ADDRESS HardwareAddress;
+ NET_ARP_ADDRESS ProtocolAddress;
+ USER_REQUEST_CONTEXT *RequestContext;
+
+ if ((This == NULL) || (TargetHwAddress == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
+
+ if (!Instance->Configured) {
+ return EFI_NOT_STARTED;
+ }
+
+ Status = EFI_SUCCESS;
+ ArpService = Instance->ArpService;
+ SnpMode = &ArpService->SnpMode;
+
+ if ((TargetSwAddress == NULL) ||
+ ((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&
+ IP4_IS_LOCAL_BROADCAST (*((UINT32 *)TargetSwAddress)))) {
+ //
+ // Return the hardware broadcast address.
+ //
+ NetCopyMem (TargetHwAddress, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);
+
+ goto SIGNAL_USER;
+ }
+
+ if ((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&
+ IP4_IS_MULTICAST (NTOHL (*((UINT32 *)TargetSwAddress)))) {
+ //
+ // If the software address is an IPv4 multicast address, invoke Mnp to
+ // resolve the address.
+ //
+ Status = ArpService->Mnp->McastIpToMac (
+ ArpService->Mnp,
+ FALSE,
+ TargetSwAddress,
+ TargetHwAddress
+ );
+ goto SIGNAL_USER;
+ }
+
+ HardwareAddress.Type = SnpMode->IfType;
+ HardwareAddress.Length = (UINT8)SnpMode->HwAddressSize;
+ HardwareAddress.AddressPtr = NULL;
+
+ ProtocolAddress.Type = Instance->ConfigData.SwAddressType;
+ ProtocolAddress.Length = Instance->ConfigData.SwAddressLength;
+ ProtocolAddress.AddressPtr = TargetSwAddress;
+
+ //
+ // Initialize the TargetHwAddrss to a zero address.
+ //
+ NetZeroMem (TargetHwAddress, SnpMode->HwAddressSize);
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Check whether the software address is in the denied table.
+ //
+ CacheEntry = ArpFindDeniedCacheEntry (ArpService, &ProtocolAddress, NULL);
+ if (CacheEntry != NULL) {
+ Status = EFI_ACCESS_DENIED;
+ goto UNLOCK_EXIT;
+ }
+
+ //
+ // Check whether the software address is already resolved.
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->ResolvedCacheTable,
+ NULL,
+ ByProtoAddress,
+ &ProtocolAddress,
+ NULL
+ );
+ if (CacheEntry != NULL) {
+ //
+ // Resolved, copy the address into the user buffer.
+ //
+ NetCopyMem (
+ TargetHwAddress,
+ CacheEntry->Addresses[Hardware].AddressPtr,
+ CacheEntry->Addresses[Hardware].Length
+ );
+
+ goto UNLOCK_EXIT;
+ }
+
+ if (ResolvedEvent == NULL) {
+ Status = EFI_NOT_READY;
+ goto UNLOCK_EXIT;
+ }
+
+ //
+ // Create a request context for this arp request.
+ //
+ RequestContext = NetAllocatePool (sizeof(USER_REQUEST_CONTEXT));
+ if (RequestContext == NULL) {
+ ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for RequestContext failed.\n"));
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNLOCK_EXIT;
+ }
+
+ RequestContext->Instance = Instance;
+ RequestContext->UserRequestEvent = ResolvedEvent;
+ RequestContext->UserHwAddrBuffer = TargetHwAddress;
+ NetListInit (&RequestContext->List);
+
+ //
+ // Check whether there is a same request.
+ //
+ CacheEntry = ArpFindNextCacheEntryInTable (
+ &ArpService->PendingRequestTable,
+ NULL,
+ ByProtoAddress,
+ &ProtocolAddress,
+ NULL
+ );
+ if (CacheEntry != NULL) {
+
+ CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;
+ CacheEntry->RetryCount = Instance->ConfigData.RetryCount;
+ } else {
+ //
+ // Allocate a cache entry for this request.
+ //
+ CacheEntry = ArpAllocCacheEntry (Instance);
+ if (CacheEntry == NULL) {
+ ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for CacheEntry failed.\n"));
+ NetFreePool (RequestContext);
+
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UNLOCK_EXIT;
+ }
+
+ //
+ // Fill the software address.
+ //
+ ArpFillAddressInCacheEntry (CacheEntry, &HardwareAddress, &ProtocolAddress);
+
+ //
+ // Add this entry into the PendingRequestTable.
+ //
+ NetListInsertTail (&ArpService->PendingRequestTable, &CacheEntry->List);
+ }
+
+ //
+ // Link this request context into the cache entry.
+ //
+ NetListInsertHead (&CacheEntry->UserRequestList, &RequestContext->List);
+
+ //
+ // Send out the ARP Request frame.
+ //
+ ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REQUEST);
+ Status = EFI_NOT_READY;
+
+UNLOCK_EXIT:
+
+ NET_UNLOCK (&ArpService->Lock);
+
+SIGNAL_USER:
+
+ if ((ResolvedEvent != NULL) && (Status == EFI_SUCCESS)) {
+ gBS->SignalEvent (ResolvedEvent);
+ }
+
+ return Status;
+}
+
+
+/**
+ This function aborts the previous ARP request (identified by This, TargetSwAddress
+ and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request().
+
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.
+ @param TargetSwAddress Pointer to the protocol address in previous
+ request session.
+ @param ResolvedEvent Pointer to the event that is used as the
+ notification event in previous request session.
+
+ @retval EFI_SUCCESS The pending request session(s) is/are aborted and
+ corresponding event(s) is/are signaled.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ This is NULL. TargetSwAddress is not NULL and
+ ResolvedEvent is NULL. TargetSwAddress is NULL and
+ ResolvedEvent is not NULL.
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.
+ @retval EFI_NOT_FOUND The request is not issued by
+ EFI_ARP_PROTOCOL.Request().
+
+**/
+EFI_STATUS
+EFIAPI
+ArpCancel (
+ IN EFI_ARP_PROTOCOL *This,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT ResolvedEvent OPTIONAL
+ )
+{
+ ARP_INSTANCE_DATA *Instance;
+ ARP_SERVICE_DATA *ArpService;
+ UINTN Count;
+
+ if ((This == NULL) ||
+ ((TargetSwAddress != NULL) && (ResolvedEvent == NULL)) ||
+ ((TargetSwAddress == NULL) && (ResolvedEvent != NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
+
+ if (!Instance->Configured) {
+ return EFI_NOT_STARTED;
+ }
+
+ ArpService = Instance->ArpService;
+
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {
+ return EFI_ACCESS_DENIED;
+ }
+
+ //
+ // Cancel the specified request.
+ //
+ Count = ArpCancelRequest (Instance, TargetSwAddress, ResolvedEvent);
+
+ NET_UNLOCK (&ArpService->Lock);
+
+ return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
+}
diff --git a/MdeModulePkg/Universal/Network/ArpDxe/ComponentName.c b/MdeModulePkg/Universal/Network/ArpDxe/ComponentName.c
new file mode 100644
index 0000000..ad92f3c
--- /dev/null
+++ b/MdeModulePkg/Universal/Network/ArpDxe/ComponentName.c
@@ -0,0 +1,156 @@
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ComponentName.c
+
+Abstract:
+
+
+**/
+
+#include "ArpDriver.h"
+
+//
+// EFI Component Name Functions
+//
+EFI_STATUS
+EFIAPI
+ArpComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ );
+
+EFI_STATUS
+EFIAPI
+ArpComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ );
+
+//
+// EFI Component Name Protocol
+//
+EFI_COMPONENT_NAME_PROTOCOL gArpComponentName = {
+ ArpComponentNameGetDriverName,
+ ArpComponentNameGetControllerName,
+ "eng"
+};
+
+STATIC EFI_UNICODE_STRING_TABLE mArpDriverNameTable[] = {
+ { "eng", L"ARP Network Service Driver" },
+ { NULL, NULL }
+};
+
+EFI_STATUS
+EFIAPI
+ArpComponentNameGetDriverName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN CHAR8 *Language,
+ OUT CHAR16 **DriverName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ Language - A pointer to a three character ISO 639-2 language identifier.
+ This is the language of the driver name that that the caller
+ is requesting, and it must match one of the languages specified
+ in SupportedLanguages. The number of languages supported by a
+ driver is up to the driver writer.
+ DriverName - A pointer to the Unicode string to return. This Unicode string
+ is the name of the driver specified by This in the language
+ specified by Language.
+
+ Returns:
+ EFI_SUCCES - The Unicode string for the Driver specified by This
+ and the language specified by Language was returned
+ in DriverName.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - DriverName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return LookupUnicodeString (
+ Language,
+ gArpComponentName.SupportedLanguages,
+ mArpDriverNameTable,
+ DriverName
+ );
+}
+
+EFI_STATUS
+EFIAPI
+ArpComponentNameGetControllerName (
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_HANDLE ChildHandle OPTIONAL,
+ IN CHAR8 *Language,
+ OUT CHAR16 **ControllerName
+ )
+/*++
+
+ Routine Description:
+ Retrieves a Unicode string that is the user readable name of the controller
+ that is being managed by an EFI Driver.
+
+ Arguments:
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
+ ControllerHandle - The handle of a controller that the driver specified by
+ This is managing. This handle specifies the controller
+ whose name is to be returned.
+ ChildHandle - The handle of the child controller to retrieve the name
+ of. This is an optional parameter that may be NULL. It
+ will be NULL for device drivers. It will also be NULL
+ for a bus drivers that wish to retrieve the name of the
+ bus controller. It will not be NULL for a bus driver
+ that wishes to retrieve the name of a child controller.
+ Language - A pointer to a three character ISO 639-2 language
+ identifier. This is the language of the controller name
+ that that the caller is requesting, and it must match one
+ of the languages specified in SupportedLanguages. The
+ number of languages supported by a driver is up to the
+ driver writer.
+ ControllerName - A pointer to the Unicode string to return. This Unicode
+ string is the name of the controller specified by
+ ControllerHandle and ChildHandle in the language specified
+ by Language from the point of view of the driver specified
+ by This.
+
+ Returns:
+ EFI_SUCCESS - The Unicode string for the user readable name in the
+ language specified by Language for the driver
+ specified by This was returned in DriverName.
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.
+ EFI_INVALID_PARAMETER - Language is NULL.
+ EFI_INVALID_PARAMETER - ControllerName is NULL.
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing
+ the controller specified by ControllerHandle and
+ ChildHandle.
+ EFI_UNSUPPORTED - The driver specified by This does not support the
+ language specified by Language.
+
+--*/
+{
+ return EFI_UNSUPPORTED;
+}
+