pxe_bc_arp.c

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

C
617
字号
      return TRUE;
    }
  }

  return FALSE;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
STATIC
EFI_STATUS
SendRequest (
  IN PXE_BASECODE_DEVICE  *Private,
  IN EFI_IP_ADDRESS       *ProtocolAddrPtr,
  IN EFI_MAC_ADDRESS      *HardwareAddrPtr
  )
/*++
Routine description:
  Transmit ARP request packet

Parameters:
  Private := Pointer to PxeBc interface
  ProtocolAddrPtr := Pointer IP address to find
  HardwareAddrPtr := Pointer to MAC address to find

Returns:
  EFI_SUCCESS := ARP request sent
  other := ARP request could not be sent
--*/
{
  EFI_PXE_BASE_CODE_MODE  *PxeBcMode;
  EFI_SIMPLE_NETWORK_MODE *SnpMode;
  ARP_PACKET              *ArpPacket;
  EFI_STATUS              Status;
  UINTN                   HardwareAddrLength;
  UINT8                   *SrcProtocolAddrPtr;
  UINT8                   *DestHardwareAddrptr;
  UINT8                   *DestProtocolAddrPtr;

  //
  //
  //
  PxeBcMode           = Private->EfiBc.Mode;
  SnpMode             = Private->SimpleNetwork->Mode;
  HardwareAddrLength  = SnpMode->HwAddressSize;

  //
  // Allocate ARP buffer
  //
  if (Private->ArpBuffer == NULL) {
    Status = gBS->AllocatePool (
                    EfiBootServicesData,
                    SnpMode->MediaHeaderSize + sizeof (ARP_PACKET),
                    &Private->ArpBuffer
                    );

    if (EFI_ERROR (Status)) {
      return Status;
    }
  }

  ArpPacket = (VOID *) (Private->ArpBuffer + SnpMode->MediaHeaderSize);

  //
  // for now, only handle one kind of hw and pr address
  //
  ArpPacket->ArpHeader            = ArpHeader;
  ArpPacket->ArpHeader.HwAddLen   = (UINT8) HardwareAddrLength;
  ArpPacket->ArpHeader.ProtAddLen = (UINT8) Private->IpLength;

  //
  // rest more generic
  //
  SrcProtocolAddrPtr  = (UINT8 *) (&ArpPacket->SrcHardwareAddr) + HardwareAddrLength;
  DestHardwareAddrptr = SrcProtocolAddrPtr + Private->IpLength;
  DestProtocolAddrPtr = DestHardwareAddrptr + HardwareAddrLength;

  EfiCopyMem (DestProtocolAddrPtr, ProtocolAddrPtr, Private->IpLength);
  EfiCopyMem (DestHardwareAddrptr, HardwareAddrPtr, HardwareAddrLength);
  EfiCopyMem (SrcProtocolAddrPtr, &PxeBcMode->StationIp, Private->IpLength);
  EfiCopyMem (
    &ArpPacket->SrcHardwareAddr,
    &SnpMode->CurrentAddress,
    HardwareAddrLength
    );

  return SendPacket (
          Private,
          Private->ArpBuffer,
          ArpPacket,
          sizeof (ARP_HEADER) + ((Private->IpLength + HardwareAddrLength) << 1),
          &SnpMode->BroadcastAddress,
          PXE_PROTOCOL_ETHERNET_ARP,
          EFI_PXE_BASE_CODE_FUNCTION_ARP
          );
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

//
// check for address - if not there, send ARP request, wait and check again
// not how it would be done in a full system
//
#define ARP_REQUEST_TIMEOUT_MS  500 // try for half a second
  
  ////////////////////////////////////////////////////////////
//
//  BC Arp Routine
//
EFI_STATUS
EFIAPI
BcArp (
  IN EFI_PXE_BASE_CODE_PROTOCOL * This,
  IN EFI_IP_ADDRESS             * ProtocolAddrPtr,
  OUT EFI_MAC_ADDRESS           * HardwareAddrPtr OPTIONAL
  )
/*++
Routine description:
  PxeBc ARP API.

Parameters:
  This := Pointer to PxeBc interface
  ProtocolAddrPtr := Pointer to IP address to find
  HardwareAddrPtr := Pointer to MAC address found.

Returns:
--*/
{
  EFI_MAC_ADDRESS     Mac;
  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;
  }

  DEBUG ((EFI_D_INFO, "\nBcArp()"));

  //
  // Issue BC command
  //
  if (ProtocolAddrPtr == NULL) {
    DEBUG (
      (EFI_D_INFO,
      "\nBcArp()  Exit #1  %Xh (%r)",
      EFI_INVALID_PARAMETER,
      EFI_INVALID_PARAMETER)
      );

    EfiReleaseLock (&Private->Lock);
    return EFI_INVALID_PARAMETER;
  }

  if (HardwareAddrPtr == NULL) {
    HardwareAddrPtr = &Mac;
  }

  EfiZeroMem (HardwareAddrPtr, Private->SimpleNetwork->Mode->HwAddressSize);

  if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) {
    DEBUG (
      (EFI_D_INFO,
      "\nBcArp()  Exit #2  %Xh (%r)",
      EFI_SUCCESS,
      EFI_SUCCESS)
      );

    EfiReleaseLock (&Private->Lock);
    return EFI_SUCCESS;
  }

  StatCode = DoArp (Private, ProtocolAddrPtr, HardwareAddrPtr);

  DEBUG ((EFI_D_INFO, "\nBcArp()  Exit #3  %Xh (%r)", StatCode, StatCode));

  EfiReleaseLock (&Private->Lock);
  return StatCode;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
DoArp (
  IN PXE_BASECODE_DEVICE  *Private,
  IN EFI_IP_ADDRESS       *ProtocolAddrPtr,
  OUT EFI_MAC_ADDRESS     *HardwareAddrPtr
  )
/*++
Routine description:
  Internal ARP implementation.

Parameters:
  Private := Pointer to PxeBc interface
  ProtocolAddrPtr := Pointer to IP address to find
  HardwareAddrPtr := Pointer to MAC address found

Returns:
  EFI_SUCCESS := MAC address found
  other := MAC address could not be found
--*/
{
  EFI_STATUS  StatCode;
  EFI_EVENT   TimeoutEvent;
  UINTN       HeaderSize;
  UINTN       BufferSize;
  UINT16      Protocol;

  DEBUG ((EFI_D_INFO, "\nDoArp()"));

  //
  //
  //
  StatCode = SendRequest (Private, ProtocolAddrPtr, HardwareAddrPtr);

  if (EFI_ERROR (StatCode)) {
    DEBUG ((EFI_D_INFO, "\nDoArp()  Exit #1  %Xh (%r)", StatCode, StatCode));
    return StatCode;
  }
  //
  //
  //
  StatCode = gBS->CreateEvent (
                    EFI_EVENT_TIMER,
                    EFI_TPL_CALLBACK,
                    NULL,
                    NULL,
                    &TimeoutEvent
                    );

  if (EFI_ERROR (StatCode)) {
    return StatCode;
  }

  StatCode = gBS->SetTimer (
                    TimeoutEvent,
                    TimerRelative,
                    ARP_REQUEST_TIMEOUT_MS * 10000
                    );

  if (EFI_ERROR (StatCode)) {
    gBS->CloseEvent (TimeoutEvent);
    return StatCode;
  }
  //
  //
  //
  for (;;) {
    StatCode = WaitForReceive (
                Private,
                EFI_PXE_BASE_CODE_FUNCTION_ARP,
                TimeoutEvent,
                &HeaderSize,
                &BufferSize,
                &Protocol
                );

    if (EFI_ERROR (StatCode)) {
      break;
    }

    if (Protocol != PXE_PROTOCOL_ETHERNET_ARP) {
      continue;
    }

    HandleArpReceive (
      Private,
      (ARP_PACKET *) (Private->ReceiveBufferPtr + HeaderSize),
      Private->ReceiveBufferPtr
      );

    if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) {
      break;
    }
  }

  DEBUG (
    (EFI_D_INFO,
    "\nDoArp()  Exit #2  %Xh, (%r)",
    StatCode,
    StatCode)
    );

  gBS->CloseEvent (TimeoutEvent);

  return StatCode;
}

/* eof - pxe_bc_arp.c */

⌨️ 快捷键说明

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