support.c

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

C
1,126
字号
                      &Private->TimeoutEvent
                      );

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    return efi_status;
  }

  efi_status = gBS->SetTimer (
                      Private->TimeoutEvent,
                      TimerRelative,
                      SecondsTimeout * 10000000 + random
                      );

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    gBS->CloseEvent (Private->TimeoutEvent);
    return efi_status;
  }

  Private->TimeoutOccurred = FALSE;

  //
  // Setup periodic event for callbacks
  //
  efi_status = gBS->CreateEvent (
                      EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL,
                      EFI_TPL_NOTIFY,
                      &periodic_notify,
                      Private,
                      &Private->PeriodicEvent
                      );

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    gBS->CloseEvent (Private->TimeoutEvent);
    return efi_status;
  }

  efi_status = gBS->SetTimer (
                      Private->PeriodicEvent,
                      TimerPeriodic,
                      1000000
                      );  /* 1/10th second */

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    gBS->CloseEvent (Private->TimeoutEvent);
    gBS->CloseEvent (Private->PeriodicEvent);
    return efi_status;
  }

  Private->PeriodicOccurred = FALSE;

  return EFI_SUCCESS;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
VOID
stop_receive_events (
  IN PXE_DHCP4_PRIVATE_DATA *Private
  )
{
  //
  //
  //
  ASSERT (Private);

  if (Private == NULL) {
    return ;
  }
  //
  //
  //
  gBS->CloseEvent (Private->TimeoutEvent);
  Private->TimeoutOccurred = FALSE;

  //
  //
  //
  gBS->CloseEvent (Private->PeriodicEvent);
  Private->PeriodicOccurred = FALSE;
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
tx_udp (
  IN PXE_DHCP4_PRIVATE_DATA *Private,
  IN EFI_IP_ADDRESS         *dest_ip,
  IN OPTIONAL EFI_IP_ADDRESS         *gateway_ip,
  IN EFI_IP_ADDRESS         *src_ip,
  IN VOID                   *buffer,
  IN UINTN                  BufferSize
  )
/*++
Routine description:
  Transmit DHCP packet.

Parameters:
  Private := Pointer to PxeDhcp4 private data
  dest_ip := Pointer to destination IP address
  gateway_ip := Pointer to gateway IP address or NULL
  src_ip := Pointer to source IP address or NULL
  buffer := Pointer to buffer to transmit
  BufferSize := Size of buffer in bytes

Returns:
  EFI_INVALID_PARAMETER := Private == NULL || dest_ip == NULL ||
    buffer == NULL || BufferSize < 300 || Private->PxeBc == NULL
  EFI_SUCCESS := Buffer was transmitted
  other := Return from PxeBc->UdpWrite()
--*/
{
  EFI_PXE_BASE_CODE_UDP_PORT  dest_port;
  EFI_PXE_BASE_CODE_UDP_PORT  src_port;
  EFI_IP_ADDRESS              zero_ip;

  //
  //
  //
  ASSERT (Private);
  ASSERT (dest_ip);
  ASSERT (buffer);
  ASSERT (BufferSize >= 300);

  if (Private == NULL || dest_ip == NULL || buffer == NULL || BufferSize < 300) {
    return EFI_INVALID_PARAMETER;
  }

  ASSERT (Private->PxeBc);

  if (Private->PxeBc == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Transmit DHCP discover packet...
  //
  EfiZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS));

  if (src_ip == NULL) {
    src_ip = &zero_ip;
  }

  dest_port = DHCP4_SERVER_PORT;
  src_port  = DHCP4_CLIENT_PORT;

  return Private->PxeBc->UdpWrite (
                          Private->PxeBc,
                          EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT,
                          dest_ip,
                          &dest_port,
                          gateway_ip,
                          src_ip,
                          &src_port,
                          NULL,
                          NULL,
                          &BufferSize,
                          buffer
                          );
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
rx_udp (
  IN PXE_DHCP4_PRIVATE_DATA *Private,
  OUT VOID                  *buffer,
  IN OUT UINTN              *BufferSize,
  IN OUT EFI_IP_ADDRESS     *dest_ip,
  IN OUT EFI_IP_ADDRESS     *src_ip,
  IN UINT16                 op_flags
  )
/*++
Routine description:
  Receive DHCP packet.

Parameters:
  Private := Pointer to PxeDhcp4 private data
  buffer := Pointer to buffer to receive DHCP packet
  BufferSize := Pointer to buffer size in bytes
  dest_ip := Pointer to destination IP address
  src_ip := Pointer to source IP address
  op_flags := UDP receive operation flags

Returns:
  EFI_INVALID_PARAMETER := 
  EFI_SUCCESS := Packet received
  other := Return from PxeBc->UdpRead()
--*/
{
  EFI_PXE_BASE_CODE_UDP_PORT  dest_port;
  EFI_PXE_BASE_CODE_UDP_PORT  src_port;

  //
  //
  //
  ASSERT (Private);
  ASSERT (buffer);
  ASSERT (dest_ip);
  ASSERT (src_ip);

  if (Private == NULL || buffer == NULL || dest_ip == NULL || src_ip == NULL || BufferSize == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  ASSERT (Private->PxeBc);

  if (Private->PxeBc == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Check for packet
  //
  *BufferSize = sizeof (DHCP4_PACKET);

  dest_port   = DHCP4_CLIENT_PORT;
  src_port    = DHCP4_SERVER_PORT;

  return Private->PxeBc->UdpRead (
                          Private->PxeBc,
                          op_flags,
                          dest_ip,
                          &dest_port,
                          src_ip,
                          &src_port,
                          NULL,
                          NULL,
                          BufferSize,
                          buffer
                          );
}

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
EFI_STATUS
tx_rx_udp (
  IN PXE_DHCP4_PRIVATE_DATA *Private,
  IN OUT EFI_IP_ADDRESS     *ServerIp,
  IN OPTIONAL EFI_IP_ADDRESS         *gateway_ip,
  IN OPTIONAL EFI_IP_ADDRESS         *client_ip,
  IN OPTIONAL EFI_IP_ADDRESS         *SubnetMask,
  IN DHCP4_PACKET           *tx_pkt,
  OUT DHCP4_PACKET          *rx_pkt,
  IN UINTN (*rx_vfy)(
      IN PXE_DHCP4_PRIVATE_DATA *Private,
      IN DHCP4_PACKET *tx_pkt,
      IN DHCP4_PACKET *rx_pkt,
      IN UINTN rx_pkt_size
    ),
  IN UINTN SecondsTimeout
  )
/*++
Routine description:
  Transmit DHCP packet and wait for replies.

Parameters:
  Private := Pointer to PxeDhcp4 private data
  ServerIp := Pointer to server IP address
  gateway_ip := Pointer to gateway IP address or NULL
  client_ip := Pointer to client IP address or NULL
  SubnetMask := Pointer to subnet mask or NULL
  tx_pkt := Pointer to DHCP packet to transmit
  rx_pkt := Pointer to DHCP packet receive buffer
  rx_vfy := Pointer to DHCP packet receive verification routine
  SecondsTimeout := Number of seconds until timeout

Returns:
  EFI_INVALID_PARAMETER := Private == NULL || ServerIp == NULL || 
    tx_pkt == NULL || rx_pkt == NULL || rx_vfy == NULL || Private->PxeBc == NULL
  EFI_ABORTED := Receive aborted
  EFI_TIMEOUT := No packets received
  EFI_SUCCESS := Packet(s) received
  other := Returns from other PxeDhcp4 support routines
--*/
{
  EFI_PXE_DHCP4_CALLBACK_STATUS CallbackStatus;
  EFI_IP_ADDRESS                dest_ip;
  EFI_IP_ADDRESS                src_ip;
  EFI_STATUS                    efi_status;
  DHCP4_OP                      *msg_size_op;
  UINTN                         pkt_size;
  UINTN                         n;
  UINT16                        msg_size;
  UINT16                        op_flags;
  BOOLEAN                       done_flag;
  BOOLEAN                       got_packet;

  //
  // Bad programmer check...
  //
  ASSERT (Private);
  ASSERT (ServerIp);
  ASSERT (tx_pkt);
  ASSERT (rx_pkt);
  ASSERT (rx_vfy);

  if (Private == NULL || ServerIp == NULL || tx_pkt == NULL || rx_pkt == NULL || rx_vfy == NULL) {
    return EFI_INVALID_PARAMETER;
  }

  ASSERT (Private->PxeBc);

  if (Private->PxeBc == NULL) {
    return EFI_INVALID_PARAMETER;
  }
  //
  // Enable UDP...
  //
  efi_status = start_udp (Private, client_ip, SubnetMask);

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    return efi_status;
  }
  //
  // Get length of transmit packet...
  //
  msg_size = DHCP4_DEFAULT_MAX_MESSAGE_SIZE;

  efi_status = find_opt (
                tx_pkt,
                DHCP4_MAX_MESSAGE_SIZE,
                0,
                &msg_size_op
                );

  if (!EFI_ERROR (efi_status)) {
    EfiCopyMem (&msg_size, msg_size_op->data, 2);

    if ((msg_size = htons (msg_size)) < 328) {
      msg_size = 328;
    }
  }
  //
  // Transmit packet...
  //
  efi_status = tx_udp (
                Private,
                ServerIp,
                gateway_ip,
                client_ip,
                tx_pkt,
                msg_size - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE)
                );

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    stop_udp (Private);
    return efi_status;
  }
  //
  // Enable periodic and timeout events...
  //
  efi_status = start_receive_events (Private, SecondsTimeout);

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    stop_udp (Private);
    return efi_status;
  }
  //
  // Wait for packet(s)...
  //
#if 0
  if (!client_ip) {
    Aprint ("client_ip == NULL    ");
  } else {
    Aprint (
      "client_ip == %d.%d.%d.%d    ",
      client_ip->v4.Addr[0],
      client_ip->v4.Addr[1],
      client_ip->v4.Addr[2],
      client_ip->v4.Addr[3]
      );
  }

  if (!ServerIp) {
    Aprint ("ServerIp == NULL\n");
  } else {
    Aprint (
      "ServerIp == %d.%d.%d.%d\n",
      ServerIp->v4.Addr[0],
      ServerIp->v4.Addr[1],
      ServerIp->v4.Addr[2],
      ServerIp->v4.Addr[3]
      );
  }
#endif

  done_flag   = FALSE;
  got_packet  = FALSE;

  while (!done_flag) {
    //
    // Check for timeout event...
    //
    if (Private->TimeoutOccurred) {
      efi_status = EFI_SUCCESS;
      break;
    }
    //
    // Check for periodic event...
    //
    if (Private->PeriodicOccurred && Private->callback != NULL) {
      CallbackStatus = EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE;

      if (Private->callback->Callback != NULL) {
        CallbackStatus = (Private->callback->Callback) (&Private->PxeDhcp4, Private->function, 0, NULL);
      }

      switch (CallbackStatus) {
      case EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE:
        break;

      case EFI_PXE_DHCP4_CALLBACK_STATUS_ABORT:
      default:
        stop_receive_events (Private);
        stop_udp (Private);
        return EFI_ABORTED;
      }

      Private->PeriodicOccurred = FALSE;
    }
    //
    // Check for packet...
    //
    if (client_ip == NULL) {
      EfiSetMem (&dest_ip, sizeof (EFI_IP_ADDRESS), 0xFF);
    } else {
      EfiCopyMem (&dest_ip, client_ip, sizeof (EFI_IP_ADDRESS));
    }

    EfiSetMem (&src_ip, sizeof (EFI_IP_ADDRESS), 0xFF);

    if (EfiCompareMem (&src_ip, &ServerIp, sizeof (EFI_IP_ADDRESS))) {
      EfiZeroMem (&src_ip, sizeof (EFI_IP_ADDRESS));
      op_flags = EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP;
    } else {
      op_flags = 0;
    }

    efi_status = rx_udp (
                  Private,
                  rx_pkt,
                  &pkt_size,
                  &dest_ip,
                  &src_ip,
                  op_flags
                  );

    if (efi_status == EFI_TIMEOUT) {
      efi_status = EFI_SUCCESS;
      continue;
    }

    if (EFI_ERROR (efi_status)) {
      break;
    }
    //
    // Some basic packet sanity checks..
    //
    if (pkt_size < 300) {
      continue;
    }

    if (rx_pkt->dhcp4.op != BOOTP_REPLY) {
      continue;
    }

    if (tx_pkt->dhcp4.htype != rx_pkt->dhcp4.htype) {
      continue;
    }

    if ((n = tx_pkt->dhcp4.hlen) != rx_pkt->dhcp4.hlen) {
      continue;
    }

    if (EfiCompareMem (&tx_pkt->dhcp4.xid, &rx_pkt->dhcp4.xid, 4)) {
      continue;
    }

    if (n != 0) {
      if (n >= 16) {
        n = 16;
      }

      if (EfiCompareMem (tx_pkt->dhcp4.chaddr, rx_pkt->dhcp4.chaddr, n)) {
        continue;
      }
    }
    //
    // Internal callback packet verification...
    //
    switch ((*rx_vfy) (Private, tx_pkt, rx_pkt, pkt_size)) {
    case -2:  /* ignore and stop */
      stop_receive_events (Private);
      stop_udp (Private);
      return EFI_ABORTED;

    case -1:  /* ignore and wait */
      continue;

    case 0:   /* accept and wait */
      break;

    case 1:   /* accept and stop */
      done_flag = TRUE;
      break;

    default:
      ASSERT (0);
    }
    //
    // External callback packet verification...
    //
    CallbackStatus = EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE;

    if (Private->callback != NULL) {
      if (Private->callback->Callback != NULL) {
        CallbackStatus = (Private->callback->Callback) (&Private->PxeDhcp4, Private->function, (UINT32) pkt_size, rx_pkt);
      }
    }

    switch (CallbackStatus) {
    case EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_CONTINUE:
      continue;

    case EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_ABORT:
      done_flag = TRUE;
      break;

    case EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_ABORT:
      stop_receive_events (Private);
      stop_udp (Private);
      return EFI_ABORTED;

    case EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE:
    default:
      break;
    }
    //
    // We did!  We did get a packet!
    //
    got_packet = TRUE;
  }
  //
  //
  //
  stop_receive_events (Private);
  stop_udp (Private);

  if (EFI_ERROR (efi_status)) {
    DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status));
    return efi_status;
  }

  if (got_packet) {
    return EFI_SUCCESS;
  } else {
    return EFI_TIMEOUT;
  }
}

/* eof - support.c */

⌨️ 快捷键说明

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