udp4main.c

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

C
886
字号
    return EFI_NOT_STARTED;
  }

  Ip = Instance->IpInfo->Ip;

  //
  // Invode the Ip instance the Udp4 instance consumes to do the actual operation.
  //
  return Ip->Routes (Ip, DeleteRoute, SubnetAddress, SubnetMask, GatewayAddress);
}

EFI_STATUS
EFIAPI
Udp4Transmit (
  IN EFI_UDP4_PROTOCOL          *This,
  IN EFI_UDP4_COMPLETION_TOKEN  *Token
  )
/*++

Routine Description:

  This function places a sending request to this instance of the EFI UDPv4 Protocol,
  alongside the transmit data that was filled by the user.

Arguments:

  This  - Pointer to the EFI_UDP4_PROTOCOL instance.
  Token - Pointer to the completion token that will be placed into the transmit queue.

Returns:

  EFI_SUCCESS           - The data has been queued for transmission.
  EFI_NOT_STARTED       - This EFI UDPv4 Protocol instance has not been started.
  EFI_NO_MAPPING        - When using a default address, configuration (DHCP, BOOTP,
                          RARP, etc.) is not finished yet.
  EFI_INVALID_PARAMETER - One or more of the following are TRUE:
                            This is NULL.
                            Token is NULL.
                            Token.Event is NULL.
                            Token.Packet.TxData is NULL.
                            Token.Packet.TxData.FragmentCount is zero.
                            Token.Packet.TxData.DataLength is not equal to the sum of
                            fragment lengths.
                            One or more of the Token.Packet.TxData.FragmentTable[].
                            FragmentLength fields is zero.
                            One or more of the Token.Packet.TxData.FragmentTable[].
                            FragmentBuffer fields is NULL.
                            Token.Packet.TxData. GatewayAddress is not a unicast IPv4
                            address if it is not NULL.
                            One or more IPv4 addresses in Token.Packet.TxData.
                            UdpSessionData are not valid unicast IPv4 addresses if the
                            UdpSessionData is not NULL.
  EFI_ACCESS_DENIED     - The transmit completion token with the same Token.Event is
                          already in the transmit queue.
  EFI_NOT_READY         - The completion token could not be queued because the
                          transmit queue is full.
  EFI_OUT_OF_RESOURCES  - Could not queue the transmit data.
  EFI_NOT_FOUND         - There is no route to the destination network or address.
  EFI_BAD_BUFFER_SIZE   - The data length is greater than the maximum UDP packet
                          size. Or the length of the IP header + UDP header + data
                          length is greater than MTU if DoNotFragment is TRUE.

--*/
{
  EFI_STATUS              Status;
  UDP4_INSTANCE_DATA      *Instance;
  EFI_TPL                 OldTpl;
  NET_BUF                 *Packet;
  EFI_UDP4_HEADER         *Udp4Header;
  EFI_UDP4_CONFIG_DATA    *ConfigData;
  IP4_ADDR                Destination;
  EFI_UDP4_TRANSMIT_DATA  *TxData;
  EFI_UDP4_SESSION_DATA   *UdpSessionData;
  UDP4_SERVICE_DATA       *Udp4Service;
  IP_IO_OVERRIDE          Override;
  UINT16                  HeadSum;

  if ((This == NULL) || (Token == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);

  if (Instance->IsNoMapping) {
    return EFI_NO_MAPPING;
  }

  if (!Instance->Configured) {
    return EFI_NOT_STARTED;
  }

  //
  // Validate the Token, if the token is invalid return the error code.
  //
  Status = Udp4ValidateTxToken (Instance, Token);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);

  if (EFI_ERROR (NetMapIterate (&Instance->TxTokens, Udp4TokenExist, Token)) ||
    EFI_ERROR (NetMapIterate (&Instance->RxTokens, Udp4TokenExist, Token))) {
    //
    // Try to find a duplicate token in the two token maps, if found, return
    // EFI_ACCESS_DENIED.
    //
    Status = EFI_ACCESS_DENIED;
    goto ON_EXIT;
  }

  TxData = Token->Packet.TxData;

  //
  // Create a net buffer to hold the user buffer and the udp header.
  //
  Packet = NetbufFromExt (
             (NET_FRAGMENT *)TxData->FragmentTable,
             TxData->FragmentCount,
             UDP4_HEADER_SIZE,
             0,
             Udp4NetVectorExtFree,
             NULL
             );
  if (Packet == NULL) {
    Status = EFI_OUT_OF_RESOURCES;
    goto ON_EXIT;
  }

  //
  // Store the IpIo in ProtoData.
  //
  Udp4Service = Instance->Udp4Service;
  *((UINTN *) &Packet->ProtoData[0]) = (UINTN) (Udp4Service->IpIo);

  Udp4Header = (EFI_UDP4_HEADER *) NetbufAllocSpace (Packet, UDP4_HEADER_SIZE, TRUE);
  ConfigData = &Instance->ConfigData;

  //
  // Fill the udp header.
  //
  Udp4Header->SrcPort      = HTONS (ConfigData->StationPort);
  Udp4Header->DstPort      = HTONS (ConfigData->RemotePort);
  Udp4Header->Length       = HTONS (Packet->TotalSize);
  Udp4Header->Checksum     = 0;

  UdpSessionData = TxData->UdpSessionData;
  Override.SourceAddress = ConfigData->StationAddress;

  if (UdpSessionData != NULL) {
    //
    // Set the SourceAddress, SrcPort and Destination according to the specified
    // UdpSessionData.
    //
    if (EFI_IP4 (UdpSessionData->SourceAddress) != 0) {
      Override.SourceAddress = UdpSessionData->SourceAddress;
    }

    if (UdpSessionData->SourcePort != 0) {
      Udp4Header->SrcPort = HTONS (UdpSessionData->SourcePort);
    }

    Destination = EFI_IP4 (UdpSessionData->DestinationAddress);

    if (UdpSessionData->DestinationPort != 0) {
      Udp4Header->DstPort = HTONS (UdpSessionData->DestinationPort);
    }

    //
    // calculate the pseudo head checksum using the overridden parameters.
    //
    HeadSum = NetPseudoHeadChecksum (
                EFI_IP4 (Override.SourceAddress),
                Destination,
                EFI_IP_PROTO_UDP,
                0
                );
  } else {
    //
    // UdpSessionData is NULL, use the address and port information previously configured.
    //
    Destination = EFI_IP4 (ConfigData->RemoteAddress);
    HeadSum     = Instance->HeadSum;
  }

  //
  // calculate the checksum.
  //
  Udp4Header->Checksum = Udp4Checksum (Packet, HeadSum);
  if (Udp4Header->Checksum == 0) {
    //
    // If the calculated checksum is 0, fill the Checksum field with all ones.
    //
    Udp4Header->Checksum = 0xffff;
  }

  //
  // Fill the IpIo Override data.
  //
  EFI_IP4 (Override.GatewayAddress) = (TxData->GatewayAddress != NULL) ?
                                      EFI_IP4 (*(TxData->GatewayAddress)) : 0;
  Override.Protocol                 = EFI_IP_PROTO_UDP;
  Override.TypeOfService            = ConfigData->TypeOfService;
  Override.TimeToLive               = ConfigData->TimeToLive;
  Override.DoNotFragment            = ConfigData->DoNotFragment;

  //
  // Save the token into the TxToken map.
  //
  Status = NetMapInsertTail (&Instance->TxTokens, Token, Packet);
  if (EFI_ERROR (Status)) {
    goto FREE_PACKET;
  }

  //
  // Send out this datagram through IpIo.
  //
  Status = IpIoSend (
             Udp4Service->IpIo,
             Packet,
             Instance->IpInfo,
             Instance,
             Token,
             Destination,
             &Override
             );
  if (EFI_ERROR (Status)) {
    //
    // Remove this token from the TxTokens.
    //
    Udp4RemoveToken (&Instance->TxTokens, Token);
  }

FREE_PACKET:

  NetbufFree (Packet);

ON_EXIT:

  NET_RESTORE_TPL (OldTpl);

  return Status;
}

EFI_STATUS
EFIAPI
Udp4Receive (
  IN EFI_UDP4_PROTOCOL          *This,
  IN EFI_UDP4_COMPLETION_TOKEN  *Token
  )
/*++

Routine Description:

  This function places a completion token into the receive packet queue. This function
  is always asynchronous.

Arguments:

  This  - Pointer to the EFI_UDP4_PROTOCOL instance.
  Token - Pointer to a token that is associated with the receive data descriptor.

Returns:

  EFI_SUCCESS           - The receive completion token is cached.
  EFI_NOT_STARTED       - This EFI UDPv4 Protocol instance has not been started.
  EFI_NO_MAPPING        - When using a default address, configuration (DHCP, BOOTP, RARP, etc.)
                          is not finished yet.
  EFI_INVALID_PARAMETER - One or more of the following conditions is TRUE:
                            This is NULL.
                            Token is NULL.
                            Token.Event is NULL.
  EFI_OUT_OF_RESOURCES  - The receive completion token could not be queued due to a lack
                          of system resources (usually memory).
  EFI_DEVICE_ERROR      - An unexpected system or network error occurred. The EFI UDPv4
                          Protocol instance has been reset to startup defaults.
  EFI_ACCESS_DENIED     - A receive completion token with the same Token.Event is already
                          in the receive queue.
  EFI_NOT_READY         - The receive request could not be queued because the receive 
                          queue is full.

--*/
{
  EFI_STATUS          Status;
  UDP4_INSTANCE_DATA  *Instance;
  EFI_TPL             OldTpl;

  if ((This == NULL) || (Token == NULL) || (Token->Event == NULL)) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);

  if (Instance->IsNoMapping) {
    return EFI_NO_MAPPING;
  }

  if (!Instance->Configured) {
    return EFI_NOT_STARTED;
  }

  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);

  if (EFI_ERROR (NetMapIterate (&Instance->RxTokens, Udp4TokenExist, Token))||
    EFI_ERROR (NetMapIterate (&Instance->TxTokens, Udp4TokenExist, Token))) {
    //
    // Return EFI_ACCESS_DENIED if the specified token is already in the TxTokens or
    // RxTokens map.
    //
    Status = EFI_ACCESS_DENIED;
    goto ON_EXIT;
  }

  Token->Packet.RxData = NULL;

  //
  // Save the token into the RxTokens map.
  //
  Status = NetMapInsertTail (&Instance->RxTokens, Token, NULL);
  if (EFI_ERROR (Status)) {
    return EFI_NOT_READY;
  }

  //
  // If there is an icmp error, report it.
  //
  Udp4ReportIcmpError (Instance);

  //
  // Try to delivered the received datagrams.
  //
  Udp4InstanceDeliverDgram (Instance);

ON_EXIT:

  NET_RESTORE_TPL (OldTpl);

  return Status;
}

EFI_STATUS
EFIAPI
Udp4Cancel (
  IN EFI_UDP4_PROTOCOL          *This,
  IN EFI_UDP4_COMPLETION_TOKEN  *Token OPTIONAL
  )
/*++

Routine Description:

  This function is used to abort a pending transmit or receive request.

Arguments:

  This  - Pointer to the EFI_UDP4_PROTOCOL instance.
  Token - Pointer to a token that has been issued by EFI_UDP4_PROTOCOL.Transmit() or
          EFI_UDP4_PROTOCOL.Receive().

Returns:

  EFI_SUCCESS           - The asynchronous I/O request is aborted and Token.Event is 
                          signaled. When Token is NULL, all pending requests are aborted
                          and their events are signaled.
  EFI_INVALID_PARAMETER - This is NULL.
  EFI_NOT_STARTED       - This instance has not been started.
  EFI_NO_MAPPING        - When using the default address, configuration (DHCP, BOOTP,
                          RARP, etc.) is not finished yet.
  EFI_NOT_FOUND         - When Token is not NULL, the asynchronous I/O request is not
                          found in the transmit or receive queue. It is either completed
                          or not issued by Transmit() or Receive().
--*/
{
  EFI_STATUS          Status;
  UDP4_INSTANCE_DATA  *Instance;
  EFI_TPL             OldTpl;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);

  if (Instance->IsNoMapping) {
    return EFI_NO_MAPPING;
  }

  if (!Instance->Configured) {
    return EFI_NOT_STARTED;
  }

  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);

  //
  // Cancle the tokens specified by Token for this instance.
  //
  Status = Udp4InstanceCancelToken (Instance, Token);

  NET_RESTORE_TPL (OldTpl);

  return Status;
}

EFI_STATUS
EFIAPI
Udp4Poll (
  IN EFI_UDP4_PROTOCOL  *This
  )
/*++

Routine Description:

  This function can be used by network drivers and applications to increase the rate that
  data packets are moved between the communications device and the transmit/receive queues.

Argumens:

  This - Pointer to the EFI_UDP4_PROTOCOL instance.

Returns:

  EFI_SUCCESS           - Incoming or outgoing data was processed.
  EFI_INVALID_PARAMETER - This is NULL.
  EFI_DEVICE_ERROR      - An unexpected system or network error occurred.
  EFI_TIMEOUT           - Data was dropped out of the transmit and/or receive queue.

--*/
{
  UDP4_INSTANCE_DATA  *Instance;
  EFI_IP4_PROTOCOL    *Ip;

  if (This == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);
  Ip       = Instance->IpInfo->Ip;

  //
  // Invode the Ip instance consumed by the udp instance to do the poll operation.
  //
  return Ip->Poll (Ip);
}

⌨️ 快捷键说明

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