pxe_bc_udp.c

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

C
577
字号

Parameters:
  Private := Pointer to PxeBc interface
  OpFlags := 
  DestIpPtr := 
  DestPortPtr := 
  SrcIpPtr := 
  SrcPortPtr := 
  HeaderSizePtr := 
  HeaderPtr := 
  BufferSizeptr := 
  BufferPtr := 
  TimeoutEvent :=

Returns:
  EFI_SUCCESS := 
  EFI_INVALID_PARAMETER := 
  other := 
--*/
{
  EFI_STATUS      StatCode;
  EFI_IP_ADDRESS  TmpSrcIp;
  EFI_IP_ADDRESS  TmpDestIp;
  UINTN           BufferSize;
  UINTN           HeaderSize;

  //
  // combination structure of pseudo header/udp header
  //
#pragma pack (1)
  struct {
    UDPV4_PSEUDO_HEADER Udpv4PseudoHeader;
    UDPV4_HEADER        Udpv4Header;
    UINT8               ProtHdr[64];
  } Hdrs;
#pragma pack ()

  HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;
  //
  // read [with filtering]
  // check parameters
  //
  if (BufferSizeptr == NULL ||
      BufferPtr == NULL ||
      (HeaderSize != 0 && HeaderPtr == NULL) ||
      (OpFlags &~UDP_FILTER_MASK)
      //
      // if filtering on a particular IP/Port, need it
      //
      ||
      (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr == NULL) ||
      (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && SrcPortPtr == NULL) ||
      (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && DestPortPtr == NULL)
      ) {
    DEBUG ((EFI_D_INFO, "\nUdpRead()  Exit #1  Invalid Parameter"));
    return EFI_INVALID_PARAMETER;
  }

  //
  // in case we loop
  //
  BufferSize = *BufferSizeptr;
  //
  // we need source and dest IPs for pseudo header
  //
  if (SrcIpPtr == NULL) {
    SrcIpPtr = &TmpSrcIp;
  }

  if (DestIpPtr == NULL) {
    DestIpPtr = &TmpDestIp;
    TmpDestIp = Private->EfiBc.Mode->StationIp;
  }

#if SUPPORT_IPV6
  if (Private->EfiBc.Mode->UsingIpv6) {
    //
    // %%TBD
    //
  }
#endif

  for (;;) {
    *BufferSizeptr = BufferSize;

    StatCode = IpReceive (
                Private,
                OpFlags,
                SrcIpPtr,
                DestIpPtr,
                PROT_UDP,
                &Hdrs.Udpv4Header,
                HeaderSize + sizeof Hdrs.Udpv4Header,
                BufferPtr,
                BufferSizeptr,
                TimeoutEvent
                );

    if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) {
      UINT16  SPort;
      UINT16  DPort;

      SPort = NTOHS (Hdrs.Udpv4Header.SrcPort);
      DPort = NTOHS (Hdrs.Udpv4Header.DestPort);

      //
      // do filtering
      //
      if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && *SrcPortPtr != SPort) {
        continue;
      }

      if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && *DestPortPtr != DPort) {
        continue;
      }
      //
      // check checksum
      //
      if (StatCode == EFI_SUCCESS && Hdrs.Udpv4Header.Checksum) {
        Hdrs.Udpv4PseudoHeader.SrcAddr.L    = SrcIpPtr->Addr[0];
        Hdrs.Udpv4PseudoHeader.DestAddr.L   = DestIpPtr->Addr[0];
        Hdrs.Udpv4PseudoHeader.Zero         = 0;
        Hdrs.Udpv4PseudoHeader.Protocol     = PROT_UDP;
        Hdrs.Udpv4PseudoHeader.TotalLength  = Hdrs.Udpv4Header.TotalLength;

        if (Hdrs.Udpv4Header.Checksum == 0xffff) {
          Hdrs.Udpv4Header.Checksum = 0;
        }

        if (IpChecksum2 (
              (UINT16 *) &Hdrs.Udpv4PseudoHeader,
              HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader) + sizeof (Hdrs.Udpv4Header),
              (UINT16 *) BufferPtr,
              *BufferSizeptr
              )) {
          DEBUG (
            (EFI_D_INFO,
            "\nUdpRead()  Hdrs.Udpv4PseudoHeader == %Xh",
            Hdrs.Udpv4PseudoHeader)
            );
          DEBUG (
            (EFI_D_INFO,
            "\nUdpRead()  Header size == %d",
            HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader))
            );
          DEBUG (
            (EFI_D_INFO,
            "\nUdpRead()  BufferPtr == %Xh",
            BufferPtr)
            );
          DEBUG (
            (EFI_D_INFO,
            "\nUdpRead()  Buffer size == %d",
            *BufferSizeptr)
            );
          DEBUG ((EFI_D_INFO, "\nUdpRead()  Exit #2  Device Error"));
          return EFI_DEVICE_ERROR;
        }
      }
      //
      // all passed
      //
      if (SrcPortPtr != NULL) {
        *SrcPortPtr = SPort;
      }

      if (DestPortPtr != NULL) {
        *DestPortPtr = DPort;
      }

      if (HeaderSize != 0) {
        EfiCopyMem (HeaderPtr, Hdrs.ProtHdr, HeaderSize);
      }
    }

    switch (StatCode) {
    case EFI_SUCCESS:
    case EFI_TIMEOUT:
      break;

    default:
      DEBUG (
        (EFI_D_INFO,
        "\nUdpRead()  Exit #3  %Xh %r",
        StatCode,
        StatCode)
        );
    }

    return StatCode;
  }
}
//
// //////////////////////////////////////////////////////////
//
//  BC Udp Read Routine
//
EFI_STATUS
EFIAPI
BcUdpRead (
  IN EFI_PXE_BASE_CODE_PROTOCOL     *This,
  IN UINT16                         OpFlags,
  IN OUT EFI_IP_ADDRESS             *DestIp, OPTIONAL
  IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL
  IN OUT EFI_IP_ADDRESS             *SrcIp, OPTIONAL
  IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL
  IN UINTN                          *HeaderSize, OPTIONAL
  IN VOID                           *HeaderPtr, OPTIONAL
  IN OUT UINTN                      *BufferSize,
  IN VOID                           *BufferPtr
  )
/*++
Routine description:
  UDP read API entry point.

Parameters:
  This := Pointer to PxeBc interface.
  OpFlags := 
  DestIpPtr := 
  DestPortPtr := 
  SrcIpPtr := 
  SrcPortPtr := 
  HeaderSizePtr := 
  HeaderPtr := 
  BufferSizeptr := 
  BufferPtr := 

Returns:
  EFI_SUCCESS := 
  other := 
--*/
{
  EFI_STATUS          StatCode;
  PXE_BASECODE_DEVICE *Private;

  //
  // Lock the instance data and make sure started
  //
  StatCode = EFI_SUCCESS;

  if (This == NULL) {
    DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);

  if (Private == NULL) {
    DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));
    return EFI_INVALID_PARAMETER;
  }

  EfiAcquireLock (&Private->Lock);

  if (This->Mode == NULL || !This->Mode->Started) {
    DEBUG ((EFI_D_ERROR, "BC was not started."));
    EfiReleaseLock (&Private->Lock);
    return EFI_NOT_STARTED;
  }

  Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_READ;

  //
  // Issue BC command
  //
  StatCode = UdpRead (
              Private,
              OpFlags,
              DestIp,
              DestPort,
              SrcIp,
              SrcPort,
              HeaderSize,
              HeaderPtr,
              BufferSize,
              BufferPtr,
              0
              );

  //
  // Unlock the instance data and return
  //
  EfiReleaseLock (&Private->Lock);
  return StatCode;
}

/* eof - pxe_bc_udp.c */

⌨️ 快捷键说明

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