/** @file
Support functions implementation for UefiPxeBc Driver.
Copyright (c) 2007 - 2011, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include "PxeBcImpl.h"
/**
Flush the previous configration using the new station Ip address.
@param[in] Private The pointer to the PxeBc private data.
@param[in] StationIp The pointer to the station Ip address.
@param[in] SubnetMask The pointer to the subnet mask address for v4.
@retval EFI_SUCCESS Successfully flushed the previous configuration.
@retval Others Failed to flush using the new station Ip.
**/
)
{
//
// Reconfigure the Ip6 instance to capture background ICMP6 packets with new station Ip address.
//
goto ON_EXIT;
}
goto ON_EXIT;
}
} else {
//
// Reconfigure the Ip4 instance to capture background ICMP packets with new station Ip address.
//
goto ON_EXIT;
}
goto ON_EXIT;
}
}
return Status;
}
/**
Notify the callback function when an event is triggered.
@param[in] Event The triggered event.
@param[in] Context The opaque parameter to the function.
**/
)
{
}
/**
Do arp resolution from arp cache in PxeBcMode.
@param Mode The pointer to EFI_PXE_BASE_CODE_MODE.
@param Ip4Addr The Ip4 address for resolution.
@param MacAddress The resoluted MAC address if the resolution is successful.
The value is undefined if the resolution fails.
@retval TRUE Found an matched entry.
@retval FALSE Did not find a matched entry.
**/
)
{
//
// Check whether the current Arp cache in mode data contains this information or not.
//
CopyMem (
sizeof (EFI_MAC_ADDRESS)
);
return TRUE;
}
}
return FALSE;
}
/**
Update the arp cache periodically.
@param Event The pointer to EFI_PXE_BC_PROTOCOL.
@param Context Context of the timer event.
**/
)
{
//
// Get the current Arp cache from Arp driver.
//
TRUE,
NULL,
&ArpEntry,
);
return;
}
//
// Update the Arp cache in mode data.
//
CopyMem (
ArpEntry + 1,
);
CopyMem (
);
}
}
/**
Notify function to handle the received ICMP message in DPC.
@param Context The PXEBC private data.
**/
)
{
if (Status == EFI_ABORTED) {
//
// It's triggered by user cancellation.
//
return;
}
goto ON_EXIT;
}
if (Status != EFI_ICMP_ERROR) {
//
// The return status should be recognized as EFI_ICMP_ERROR.
//
goto ON_EXIT;
}
//
// The source address of the received packet should be a valid unicast address.
//
goto ON_EXIT;
}
//
// The destination address of the received packet should be equal to the host address.
//
goto ON_EXIT;
}
//
// The protocol value in the header of the receveid packet should be EFI_IP_PROTO_ICMP.
//
goto ON_EXIT;
}
if (Type != ICMP_DEST_UNREACHABLE &&
Type != ICMP_SOURCE_QUENCH &&
Type != ICMP_REDIRECT &&
Type != ICMP_TIME_EXCEEDED &&
Type != ICMP_PARAMETER_PROBLEM) {
//
// The type of the receveid ICMP message should be ICMP_ERROR_MESSAGE.
//
goto ON_EXIT;
}
//
// Copy the right ICMP error message into mode data.
//
CopiedLen = 0;
if (CopiedLen <= sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)) {
CopyMem (
);
} else {
CopyMem (
CopiedLen - sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)
);
}
}
}
/**
Callback function to update the latest ICMP6 error message.
@param Event The event signalled.
@param Context The context passed in using the event notifier.
**/
)
{
}
/**
Notify function to handle the received ICMP6 message in DPC.
@param Context The PXEBC private data.
**/
)
{
if (Status == EFI_ABORTED) {
//
// It's triggered by user cancellation.
//
return;
}
goto ON_EXIT;
}
if (Status != EFI_ICMP_ERROR) {
//
// The return status should be recognized as EFI_ICMP_ERROR.
//
goto ON_EXIT;
}
//
// The source address of the received packet should be a valid unicast address.
//
goto ON_EXIT;
}
//
// The destination address of the received packet should be equal to the host address.
//
goto ON_EXIT;
}
//
// The nextheader in the header of the receveid packet should be IP6_ICMP.
//
goto ON_EXIT;
}
if (Type != ICMP_V6_DEST_UNREACHABLE &&
Type != ICMP_V6_PACKET_TOO_BIG &&
Type != ICMP_V6_PACKET_TOO_BIG &&
//
// The type of the receveid packet should be an ICMP6 error message.
//
goto ON_EXIT;
}
//
// Copy the right ICMP6 error message into mode data.
//
CopiedLen = 0;
if (CopiedLen <= sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)) {
CopyMem (
);
} else {
CopyMem (
CopiedLen - sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)
);
}
Icmp6Error += CopiedLen;
}
}
/**
Callback function to update the latest ICMP6 error message.
@param Event The event signalled.
@param Context The context passed in using the event notifier.
**/
)
{
}
/**
This function is to configure a UDPv4 instance for UdpWrite.
@param[in] Udp4 The pointer to EFI_UDP4_PROTOCOL.
@param[in] StationIp The pointer to the station address.
@param[in] SubnetMask The pointer to the subnet mask.
@param[in] Gateway The pointer to the gateway address.
@param[in, out] SrcPort The pointer to the source port.
@param[in] DoNotFragment If TRUE, fragment is not enabled.
Otherwise, fragment is enabled.
@retval EFI_SUCCESS Successfully configured this instance.
@retval Others Failed to configure this instance.
**/
)
{
//
// Reset the UDPv4 instance.
//
//
// The basic configuration is OK, need to add the default route entry
//
}
}
}
return Status;
}
/**
This function is to configure a UDPv6 instance for UdpWrite.
@param[in] Udp6 The pointer to EFI_UDP6_PROTOCOL.
@param[in] StationIp The pointer to the station address.
@param[in, out] SrcPort The pointer to the source port.
@retval EFI_SUCCESS Successfully configured this instance.
@retval Others Failed to configure this instance.
**/
)
{
//
// Reset the UDPv6 instance.
//
return Status;
}
}
return Status;
}
/**
This function is to configure a UDPv4 instance for UdpWrite.
@param[in] Udp4 The pointer to EFI_UDP4_PROTOCOL.
@param[in] Session The pointer to the UDP4 session data.
@param[in] TimeoutEvent The event for timeout.
@param[in] Gateway The pointer to the gateway address.
@param[in] HeaderSize An optional field which may be set to the length of a header
at HeaderPtr to be prefixed to the data at BufferPtr.
@param[in] HeaderPtr If HeaderSize is not NULL, a pointer to a header to be
prefixed to the data at BufferPtr.
@param[in] BufferSize A pointer to the size of the data at BufferPtr.
@param[in] BufferPtr A pointer to the data to be written.
@retval EFI_SUCCESS Successfully send out data using Udp4Write.
@retval Others Failed to send out data.
**/
)
{
//
// Arrange one fragment buffer for data, and another fragment buffer for header if has.
//
return EFI_OUT_OF_RESOURCES;
}
if (HeaderSize != NULL) {
}
}
&IsDone,
);
goto ON_EXIT;
}
goto ON_EXIT;
}
//
// Poll the UDPv6 read instance if no packet received and no timeout triggered.
//
while (!IsDone &&
}
}
return Status;
}
/**
This function is to configure a UDPv4 instance for UdpWrite.
@param[in] Udp6 The pointer to EFI_UDP6_PROTOCOL.
@param[in] Session The pointer to the UDP6 session data.
@param[in] TimeoutEvent The event for timeout.
@param[in] HeaderSize An optional field which may be set to the length of a header
at HeaderPtr to be prefixed to the data at BufferPtr.
@param[in] HeaderPtr If HeaderSize is not NULL, a pointer to a header to be
prefixed to the data at BufferPtr.
@param[in] BufferSize A pointer to the size of the data at BufferPtr.
@param[in] BufferPtr A pointer to the data to be written.
@retval EFI_SUCCESS Successfully sent out data using Udp6Write.
@retval Others Failed to send out data.
**/
)
{
//
// Arrange one fragment buffer for data, and another fragment buffer for header if has.
//
return EFI_OUT_OF_RESOURCES;
}
if (HeaderSize != NULL) {
}
&IsDone,
);
goto ON_EXIT;
}
goto ON_EXIT;
}
//
// Poll the UDPv6 read instance if no packet received and no timeout triggered.
//
while (!IsDone &&
}
}
return Status;
}
/**
Check the received packet using the Ip filter.
@param[in] Mode The pointer to the mode data of PxeBc.
@param[in] Session The pointer to the current UDPv4 session.
@retval TRUE Passed the Ip filter successfully.
@retval FALSE Failed to pass the Ip filter.
**/
)
{
if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) == 0) {
return TRUE;
}
return TRUE;
}
//
// Convert the destination address in session data to host order.
//
CopyMem (
sizeof (EFI_IPv6_ADDRESS)
);
} else {
CopyMem (
sizeof (EFI_IPv4_ADDRESS)
);
}
IP6_IS_MULTICAST (&DestinationIp))) {
return TRUE;
}
return TRUE;
}
//
// Matched if the dest address is equal to the station address.
//
return TRUE;
}
//
// Matched if the dest address is equal to any of address in the filter list.
//
return TRUE;
}
}
return FALSE;
}
/**
Filter the received packet using the destination Ip.
@param[in] Mode The pointer to the mode data of PxeBc.
@param[in] Session The pointer to the current UDPv4 session.
@param[in, out] DestIp The pointer to the destination Ip address.
@retval TRUE Passed the IPv4 filter successfully.
@retval FALSE Failed to pass the IPv4 filter.
**/
)
{
if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP) != 0) {
//
// Copy the destination address from the received packet if accept any.
//
CopyMem (
sizeof (EFI_IPv6_ADDRESS)
);
} else {
CopyMem (
sizeof (EFI_IPv4_ADDRESS)
);
}
}
return TRUE;
//
// The destination address in the received packet is matched if present.
//
return TRUE;
} else if (EFI_IP4_EQUAL (&Mode->StationIp, &((EFI_UDP4_SESSION_DATA *)Session)->DestinationAddress) ||
//
// The destination address in the received packet is equal to the host address.
//
return TRUE;
}
return FALSE;
}
/**
Check the received packet using the destination port.
@param[in] Mode The pointer to the mode data of PxeBc.
@param[in] Session The pointer to the current UDPv4 session.
@param[in, out] DestPort The pointer to the destination port.
@retval TRUE Passed the IPv4 filter successfully.
@retval FALSE Failed to pass the IPv4 filter.
**/
)
{
} else {
}
if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) != 0) {
//
// Return the destination port in the received packet if accept any.
//
}
return TRUE;
//
// The destination port in the received packet is matched if present.
//
return TRUE;
}
return FALSE;
}
/**
Filter the received packet using the source Ip.
@param[in] Mode The pointer to the mode data of PxeBc.
@param[in] Session The pointer to the current UDPv4 session.
@param[in, out] SrcIp The pointer to the source Ip address.
@retval TRUE Passed the IPv4 filter successfully.
@retval FALSE Failed to pass the IPv4 filter.
**/
)
{
if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) != 0) {
//
// Copy the source address from the received packet if accept any.
//
CopyMem (
sizeof (EFI_IPv6_ADDRESS)
);
} else {
CopyMem (
sizeof (EFI_IPv4_ADDRESS)
);
}
}
return TRUE;
//
// The source address in the received packet is matched if present.
//
return TRUE;
}
return FALSE;
}
/**
Filter the received packet using the source port.
@param[in] Mode The pointer to the mode data of PxeBc.
@param[in] Session The pointer to the current UDPv4 session.
@param[in, out] SrcPort The pointer to the source port.
@retval TRUE Passed the IPv4 filter successfully.
@retval FALSE Failed to pass the IPv4 filter.
**/
)
{
} else {
}
if ((OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) != 0) {
//
// Return the source port in the received packet if accept any.
//
}
return TRUE;
//
// The source port in the received packet is matched if present.
//
return TRUE;
}
return FALSE;
}
/**
This function is to receive packet using Udp4Read.
@param[in] Udp4 The pointer to EFI_UDP4_PROTOCOL.
@param[in] Token The pointer to EFI_UDP4_COMPLETION_TOKEN.
@param[in] Mode The pointer to EFI_PXE_BASE_CODE_MODE.
@param[in] TimeoutEvent The event for timeout.
@param[in] OpFlags The UDP operation flags.
@param[in] IsDone The pointer to the IsDone flag.
@param[out] IsMatched The pointer to the IsMatched flag.
@param[in, out] DestIp The pointer to the destination address.
@param[in, out] DestPort The pointer to the destination port.
@param[in, out] SrcIp The pointer to the source address.
@param[in, out] SrcPort The pointer to the source port.
@retval EFI_SUCCESS Successfully read the data using Udp4.
@retval Others Failed to send out data.
**/
)
{
return Status;
}
//
// Poll the UDPv6 read instance if no packet received and no timeout triggered.
//
while (!(*IsDone) &&
//
//
break;
}
}
//
// check whether this packet matches the filters
//
if (*IsMatched) {
}
if (*IsMatched) {
}
if (*IsMatched) {
}
if (*IsMatched) {
}
if (!(*IsMatched)) {
//
// Recycle the receiving buffer if not matched.
//
}
}
return Status;
}
/**
This function is to receive packets using Udp6Read.
@param[in] Udp6 The pointer to EFI_UDP6_PROTOCOL.
@param[in] Token The pointer to EFI_UDP6_COMPLETION_TOKEN.
@param[in] Mode The pointer to EFI_PXE_BASE_CODE_MODE.
@param[in] TimeoutEvent The event for timeout.
@param[in] OpFlags The UDP operation flags.
@param[in] IsDone The pointer to the IsDone flag.
@param[out] IsMatched The pointer to the IsMatched flag.
@param[in, out] DestIp The pointer to the destination address.
@param[in, out] DestPort The pointer to the destination port.
@param[in, out] SrcIp The pointer to the source address.
@param[in, out] SrcPort The pointer to the source port.
@retval EFI_SUCCESS Successfully read data using Udp6.
@retval Others Failed to send out data.
**/
)
{
return Status;
}
//
// Poll the UDPv6 read instance if no packet received and no timeout triggered.
//
while (!(*IsDone) &&
//
//
break;
}
}
//
// check whether this packet matches the filters
//
if (*IsMatched) {
}
if (*IsMatched) {
}
if (*IsMatched) {
}
if (*IsMatched) {
}
if (!(*IsMatched)) {
//
// Recycle the receiving buffer if not matched.
//
}
}
return Status;
}
/**
This function is to display the IPv4 address.
@param[in] Ip The pointer to the IPv4 address.
**/
)
{
if (Index < 3) {
AsciiPrint (".");
}
}
}
/**
This function is to display the IPv6 address.
@param[in] Ip The pointer to the IPv6 address.
**/
)
{
}
Index++;
if (Index > 15) {
return;
}
AsciiPrint ("0");
}
if (Index < 15) {
AsciiPrint (":");
}
}
}
/**
This function is to convert UINTN to ASCII string with the required formatting.
@param[in] Number Numeric value to be converted.
@param[in] Buffer The pointer to the buffer for ASCII string.
@param[in] Length The length of the required format.
**/
)
{
while (Length > 0) {
Length--;
Number /= 10;
}
}
/**
This function is to convert a UINTN to a ASCII string, and return the
actual length of the buffer.
@param[in] Number Numeric value to be converted.
@param[in] Buffer The pointer to the buffer for ASCII string.
@return Length The actual length of the ASCII string.
**/
)
{
Index = 63;
do {
Index--;
} while (Number != 0);
return Length;
}
/**
This function is to convert unicode hex number to a UINT8.
@param[out] Digit The converted UINT8 for output.
@param[in] Char The unicode hex number to be converted.
@retval EFI_SUCCESS Successfully converted the unicode hex.
@retval EFI_INVALID_PARAMETER Failed to convert the unicode hex.
**/
)
{
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
return EFI_SUCCESS;
}
return EFI_INVALID_PARAMETER;
}
/**
Calculate the elapsed time.
@param[in] Private The pointer to PXE private data
**/
)
{
//
//
CurrentStamp = (UINT64)
(
);
//
// Sentinel value of 0 means that this is the first DHCP packet that we are
// sending and that we need to initialize the value. First DHCP Solicit
// gets 0 elapsed-time. Otherwise, calculate based on StartTime.
//
if (Private->ElapsedTime == 0) {
} else {
//
// If elapsed time cannot fit in two bytes, set it to 0xffff.
//
if (ElapsedTimeValue > 0xffff) {
ElapsedTimeValue = 0xffff;
}
//
// Save the elapsed time
//
}
}