arpmain.c

来自「EFI BIOS是Intel提出的下一代的BIOS标准。这里上传的Edk源代码是」· C语言 代码 · 共 757 行 · 第 1/2 页

C
757
字号
  EFI_SUCCESS           - The entry was removed from the ARP cache.
  EFI_INVALID_PARAMETER - This is NULL.
  EFI_NOT_FOUND         - The specified deletion key was not found.
  EFI_NOT_STARTED       - The ARP driver instance has not been configured.

--*/
{
  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;
}

EFI_STATUS
EFIAPI
ArpFlush (
  IN EFI_ARP_PROTOCOL  *This
  )
/*++

Routine Description:

  This function delete all dynamic entries from the ARP cache that match the specified
  software protocol type.

Arguments:

  This - Pointer to the EFI_ARP_PROTOCOL instance.

Returns:

  EFI_SUCCESS           - The cache has been flushed.
  EFI_INVALID_PARAMETER - This is NULL.
  EFI_NOT_FOUND         - There are no matching dynamic cache entries.
  EFI_NOT_STARTED       - The ARP driver instance has not been configured.

--*/
{
  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;
}

EFI_STATUS
EFIAPI
ArpRequest (
  IN EFI_ARP_PROTOCOL  *This,
  IN VOID              *TargetSwAddress OPTIONAL,
  IN EFI_EVENT         ResolvedEvent    OPTIONAL,
  OUT VOID             *TargetHwAddress
  )
/*++

Routine Description:

  This function tries to resolve the TargetSwAddress and optionally returns a 
  TargetHwAddress if it already exists in the ARP cache.

Arguments:

  This            - Pointer to the EFI_ARP_PROTOCOL instance.
  TargetSwAddress - Pointer to the protocol address to resolve.
  ResolvedEvent   - Pointer to the event that will be signaled when the address is
                    resolved or some error occurs.
  TargetHwAddress - Pointer to the buffer for the resolved hardware address in
                    network byte order.

Returns:

  EFI_SUCCESS           - The data is copied from the ARP cache into the TargetHwAddress
                          buffer.
  EFI_INVALID_PARAMETER - One or more of the following conditions is TRUE:
                            This is NULL.
                            TargetHwAddress is NULL.
  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.
  EFI_NOT_STARTED       - The ARP driver instance has not been configured.
  EFI_NOT_READY         - The request has been started and is not finished.

--*/
{
  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;
}

EFI_STATUS
EFIAPI
ArpCancel (
  IN EFI_ARP_PROTOCOL  *This,
  IN VOID              *TargetSwAddress OPTIONAL,
  IN EFI_EVENT         ResolvedEvent    OPTIONAL
  )
/*++

Routine Description:

  This function aborts the previous ARP request (identified by This,  TargetSwAddress
  and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request().

Arguments:

  This            - Pointer to the EFI_ARP_PROTOCOL instance.
  TargetSwAddress - Pointer to the protocol address in previous request session.
  ResolvedEvent   - Pointer to the event that is used as the notification event in
                    previous request session.

Returns:

  EFI_SUCCESS           - The pending request session(s) is/are aborted and corresponding
                          event(s) is/are signaled.
  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.
  EFI_NOT_STARTED       - The ARP driver instance has not been configured.
  EFI_NOT_FOUND         - The request is not issued by EFI_ARP_PROTOCOL.Request().

--*/
{
  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;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?