pxe_bc_tcp.c

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

C
665
字号
Parameters:
  Private := Pointer to PxeBc interface
  OpFlags := 
  DestIpPtr := 
  DestPortPtr := 
  SrcIpPtr := 
  SrcPortPtr := 
  HeaderSizePtr := 
  HeaderPtr := 
  BufferSizePtr := 
  BufferPtr := 

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

  //
  // combination structure of pseudo header/tcp header
  //
#pragma pack (1)
  struct {
    IPV4_HEADER         Ipv4Hdr;
    TCPV4_PSEUDO_HEADER Tcpv4Phdr;
    TCPV4_HEADER        Tcpv4Hdr;
    UINT8               ProtHdr[64];
  } Hdrs;
#pragma pack ()

  HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0;
  //
  // Yes, I now require a Header Allocated
  //
  if (HeaderPtr == 0) {
    return EFI_DEVICE_ERROR;
  }

  HeaderSize = sizeof Hdrs.Ipv4Hdr + sizeof Hdrs.Tcpv4Hdr;
  EfiZeroMem (Hdrs.ProtHdr, 64);

  Hdrs.ProtHdr[0] = 'M';
  Hdrs.ProtHdr[1] = 'A';
  Hdrs.ProtHdr[2] = 'R';
  Hdrs.ProtHdr[3] = 'M';
  Hdrs.ProtHdr[4] = 'A';
  Hdrs.ProtHdr[5] = 'R';

  DEBUG ((EFI_D_NET, "\nTcpRead()  BufferSize = %xh", *BufferSizePtr));

  //
  // 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, "\nTcpRead()  Exit #1  Invalid Parameter"));
    return EFI_INVALID_PARAMETER;
  }

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

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

  for (;;) {
    *BufferSizePtr = BufferSize;

    DEBUG ((EFI_D_NET, "\nSize of Hdrs.Tcpv4Hdr = %d", sizeof Hdrs.Tcpv4Hdr));

    //
    // Let's receive the IP and TCP header at the Hdrs.Ipv4Hdr location
    // and the data for the TCP will be passed back in the BufferPtr.
    //
    StatCode = IpReceive (
                Private,
                OpFlags,
                SrcIpPtr,
                DestIpPtr,
                PROT_TCP,
                HeaderPtr,
                HeaderSize,
                BufferPtr,
                BufferSizePtr,
                0
                );

    EfiCopyMem (&Hdrs.Ipv4Hdr, HeaderPtr, HeaderSize);

    DEBUG (
      (EFI_D_NET,
      "\nTcpRead()  BufferSize = %xh  Ipv+Tcp = %d",
      *BufferSizePtr,
      sizeof Hdrs.Ipv4Hdr + sizeof Hdrs.Tcpv4Hdr)
      );

    DEBUG (
      (EFI_D_NET,
      "\nTcpRead()  Destination IP address is:  %d.%d.%d.%d\n",
      Hdrs.Ipv4Hdr.DestAddr.B[0],
      Hdrs.Ipv4Hdr.DestAddr.B[1],
      Hdrs.Ipv4Hdr.DestAddr.B[2],
      Hdrs.Ipv4Hdr.DestAddr.B[3])
      );

    DEBUG (
      (EFI_D_NET,
      "\nTcpRead()  Source IP address is:  %d.%d.%d.%d\n",
      Hdrs.Ipv4Hdr.SrcAddr.B[0],
      Hdrs.Ipv4Hdr.SrcAddr.B[1],
      Hdrs.Ipv4Hdr.SrcAddr.B[2],
      Hdrs.Ipv4Hdr.SrcAddr.B[3])
      );

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

      SPort = NTOHS (Hdrs.Tcpv4Hdr.SrcPort);
      DPort = NTOHS (Hdrs.Tcpv4Hdr.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.Tcpv4Hdr.Checksum) {
        Hdrs.Tcpv4Phdr.SrcAddr.L    = SrcIpPtr->Addr[0];
        Hdrs.Tcpv4Phdr.DestAddr.L   = DestIpPtr->Addr[0];
        Hdrs.Tcpv4Phdr.Zero         = 0;
        Hdrs.Tcpv4Phdr.Protocol     = PROT_TCP;
        Hdrs.Tcpv4Phdr.TotalLength  = (UINT16) (NTOHS (Hdrs.Ipv4Hdr.TotalLength) - sizeof Hdrs.Ipv4Hdr);
        Hdrs.Tcpv4Phdr.TotalLength  = HTONS (Hdrs.Tcpv4Phdr.TotalLength);

        if (Hdrs.Tcpv4Hdr.Checksum == 0xffff) {
          Hdrs.Tcpv4Hdr.Checksum = 0;
        }
        //
        // The HeaderPtr has the IP header in it, let's skip it and start the
        // checksum at the TCP pseudo header.
        //
        if (IpChecksum2 (
              (UINT16 *) HeaderPtr + sizeof Hdrs.Ipv4Hdr,
              sizeof Hdrs.Tcpv4Hdr + sizeof Hdrs.Tcpv4Phdr,
              (UINT16 *) BufferPtr,
              *BufferSizePtr
              )) {
          DEBUG (
            (EFI_D_NET,
            "\nTcpRead()  Hdrs.Ipv4hdr == %xh",
            &Hdrs.Ipv4Hdr)
            );
          DEBUG (
            (EFI_D_NET,
            "\nTcpRead()  Hdrs.Tcpv4hdr == %xh",
            &Hdrs.Tcpv4Hdr)
            );
          DEBUG ((EFI_D_NET, "\nTcpRead()  Header size == %d", HeaderSize));
          DEBUG ((EFI_D_NET, "\nTcpRead()  BufferPtr == %xh", BufferPtr));
          DEBUG ((EFI_D_NET, "\nTcpRead()  Buffer size == %d", *BufferSizePtr));
          DEBUG ((EFI_D_NET, "\nTcpRead()  Exit #2  Device Error"));

          //
          // Invalid checksum for a zero lenght buffer is okay.
          //
          if (*BufferSizePtr > 0) {
            return EFI_DEVICE_ERROR;
          }
        }
      }

      DEBUG ((EFI_D_NET, "\nTcpRead()  PASSED!!!!!!!!"));

      //
      // all passed
      //
      if (SrcPortPtr != NULL) {
        *SrcPortPtr = SPort;
      }

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

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

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

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

Parameters:
  This := Pointer to PxeBc interface
  OpFlags := 
  DestIp := 
  DestPort := 
  SrcIp := 
  SrcPort := 
  HeaderSize := 
  HeaderPtr := 
  BufferSize := 
  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_TCP_READ;

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

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

/* eof - pxe_bc_tcp.c */

⌨️ 快捷键说明

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