mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-11-04 10:19:50 +00:00 
			
		
		
		
	git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10418 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			746 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			746 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Implementation of EFI Address Resolution Protocol (ARP) Protocol interface functions.
 | 
						|
  
 | 
						|
Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
 | 
						|
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<BR>
 | 
						|
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.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "ArpImpl.h"
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This function is used to assign a station address to the ARP cache for this instance
 | 
						|
  of the ARP driver.
 | 
						|
  
 | 
						|
  Each ARP instance has one station address. The EFI_ARP_PROTOCOL driver will 
 | 
						|
  respond to ARP requests that match this registered station address. A call to 
 | 
						|
  this function with the ConfigData field set to NULL will reset this ARP instance.
 | 
						|
  
 | 
						|
  Once a protocol type and station address have been assigned to this ARP instance, 
 | 
						|
  all the following ARP functions will use this information. Attempting to change 
 | 
						|
  the protocol type or station address to a configured ARP instance will result in errors.
 | 
						|
 | 
						|
  @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;
 | 
						|
  EFI_TPL            OldTpl;
 | 
						|
 | 
						|
  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);
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // Configure this instance, the ConfigData has already passed the basic checks.
 | 
						|
  //
 | 
						|
  Status = ArpConfigureInstance (Instance, ConfigData);
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This function is used to insert entries into the ARP cache.
 | 
						|
 | 
						|
  ARP cache entries are typically inserted and updated by network protocol drivers 
 | 
						|
  as network traffic is processed. Most ARP cache entries will time out and be 
 | 
						|
  deleted if the network traffic stops. ARP cache entries that were inserted 
 | 
						|
  by the Add() function may be static (will not time out) or dynamic (will time out).
 | 
						|
  Default ARP cache timeout values are not covered in most network protocol 
 | 
						|
  specifications (although RFC 1122 comes pretty close) and will only be 
 | 
						|
  discussed in general in this specification. The timeout values that are 
 | 
						|
  used in the EFI Sample Implementation should be used only as a guideline. 
 | 
						|
  Final product implementations of the EFI network stack should be tuned for 
 | 
						|
  their expected network environments.
 | 
						|
  
 | 
						|
  @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];
 | 
						|
  EFI_TPL                  OldTpl;
 | 
						|
 | 
						|
  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;
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // 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.
 | 
						|
    //
 | 
						|
    RemoveEntryList (&CacheEntry->List);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // It's a new entry, allocate memory for the entry.
 | 
						|
    //
 | 
						|
    CacheEntry = ArpAllocCacheEntry (Instance);
 | 
						|
 | 
						|
    if (CacheEntry == NULL) {
 | 
						|
      DEBUG ((EFI_D_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) {
 | 
						|
    InsertHeadList (&ArpService->DeniedCacheTable, &CacheEntry->List);
 | 
						|
  } else {
 | 
						|
    InsertHeadList (&ArpService->ResolvedCacheTable, &CacheEntry->List);
 | 
						|
  }
 | 
						|
 | 
						|
UNLOCK_EXIT:
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This function searches the ARP cache for matching entries and allocates a buffer into
 | 
						|
  which those entries are copied.
 | 
						|
  
 | 
						|
  The first part of the allocated buffer is EFI_ARP_FIND_DATA, following which 
 | 
						|
  are protocol address pairs and hardware address pairs.
 | 
						|
  When finding a specific protocol address (BySwAddress is TRUE and AddressBuffer 
 | 
						|
  is not NULL), the ARP cache timeout for the found entry is reset if Refresh is 
 | 
						|
  set to TRUE. If the found ARP cache entry is a permanent entry, it is not 
 | 
						|
  affected by Refresh.
 | 
						|
  
 | 
						|
  @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;
 | 
						|
  EFI_TPL            OldTpl;
 | 
						|
 | 
						|
  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);
 | 
						|
 | 
						|
  if (!Instance->Configured) {
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // All the check passed, find the cache entries now.
 | 
						|
  //
 | 
						|
  Status = ArpFindCacheEntry (
 | 
						|
             Instance,
 | 
						|
             BySwAddress,
 | 
						|
             AddressBuffer,
 | 
						|
             EntryLength,
 | 
						|
             EntryCount,
 | 
						|
             Entries,
 | 
						|
             Refresh
 | 
						|
             );
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  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;
 | 
						|
  UINTN              Count;
 | 
						|
  EFI_TPL            OldTpl;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (!Instance->Configured) {
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // Delete the specified cache entries.
 | 
						|
  //
 | 
						|
  Count = ArpDeleteCacheEntry (Instance, BySwAddress, AddressBuffer, TRUE);
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  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;
 | 
						|
  UINTN              Count;
 | 
						|
  EFI_TPL            OldTpl;
 | 
						|
 | 
						|
  if (This == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Instance = ARP_INSTANCE_DATA_FROM_THIS (This);
 | 
						|
 | 
						|
  if (!Instance->Configured) {
 | 
						|
    return EFI_NOT_STARTED;
 | 
						|
  }
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // Delete the dynamic entries from the cache table.
 | 
						|
  //
 | 
						|
  Count = ArpDeleteCacheEntry (Instance, FALSE, NULL, FALSE);
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  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;
 | 
						|
  EFI_TPL                  OldTpl;
 | 
						|
 | 
						|
  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.
 | 
						|
    //
 | 
						|
    CopyMem (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.
 | 
						|
  //
 | 
						|
  ZeroMem (TargetHwAddress, SnpMode->HwAddressSize);
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // 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.
 | 
						|
    //
 | 
						|
    CopyMem (
 | 
						|
      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 = AllocatePool (sizeof(USER_REQUEST_CONTEXT));
 | 
						|
  if (RequestContext == NULL) {
 | 
						|
    DEBUG ((EFI_D_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;
 | 
						|
  InitializeListHead (&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) {
 | 
						|
      DEBUG ((EFI_D_ERROR, "ArpRequest: Allocate memory for CacheEntry failed.\n"));
 | 
						|
      FreePool (RequestContext);
 | 
						|
 | 
						|
      Status = EFI_OUT_OF_RESOURCES;
 | 
						|
      goto UNLOCK_EXIT;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Fill the software address.
 | 
						|
    //
 | 
						|
    ArpFillAddressInCacheEntry (CacheEntry, &HardwareAddress, &ProtocolAddress);
 | 
						|
 | 
						|
    //
 | 
						|
    // Add this entry into the PendingRequestTable.
 | 
						|
    //
 | 
						|
    InsertTailList (&ArpService->PendingRequestTable, &CacheEntry->List);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Link this request context into the cache entry.
 | 
						|
  //
 | 
						|
  InsertHeadList (&CacheEntry->UserRequestList, &RequestContext->List);
 | 
						|
 | 
						|
  //
 | 
						|
  // Send out the ARP Request frame.
 | 
						|
  //
 | 
						|
  ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REQUEST);
 | 
						|
  Status = EFI_NOT_READY;
 | 
						|
 | 
						|
UNLOCK_EXIT:
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
SIGNAL_USER:
 | 
						|
 | 
						|
  if ((ResolvedEvent != NULL) && (Status == EFI_SUCCESS)) {
 | 
						|
    gBS->SignalEvent (ResolvedEvent);
 | 
						|
 | 
						|
    //
 | 
						|
    // Dispatch the DPC queued by the NotifyFunction of ResolvedEvent.
 | 
						|
    //
 | 
						|
    DispatchDpc ();
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  This function aborts the previous ARP request (identified by This,  TargetSwAddress
 | 
						|
  and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request().
 | 
						|
  
 | 
						|
  If the request is in the internal ARP request queue, the request is aborted 
 | 
						|
  immediately and its ResolvedEvent is signaled. Only an asynchronous address 
 | 
						|
  request needs to be canceled. If TargeSwAddress and ResolveEvent are both 
 | 
						|
  NULL, all the pending asynchronous requests that have been issued by This 
 | 
						|
  instance will be cancelled and their corresponding events will be signaled.
 | 
						|
  
 | 
						|
  @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;
 | 
						|
  UINTN              Count;
 | 
						|
  EFI_TPL            OldTpl;
 | 
						|
 | 
						|
  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;
 | 
						|
  }
 | 
						|
 | 
						|
  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
 | 
						|
 | 
						|
  //
 | 
						|
  // Cancel the specified request.
 | 
						|
  //
 | 
						|
  Count = ArpCancelRequest (Instance, TargetSwAddress, ResolvedEvent);
 | 
						|
 | 
						|
  //
 | 
						|
  // Dispatch the DPCs queued by the NotifyFunction of the events signaled
 | 
						|
  // by ArpCancleRequest.
 | 
						|
  //
 | 
						|
  DispatchDpc ();
 | 
						|
 | 
						|
  gBS->RestoreTPL (OldTpl);
 | 
						|
 | 
						|
  return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;
 | 
						|
}
 |