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 + -
显示快捷键?