BOOLEAN Notify;\r
} ICMP_ERROR_INFO;\r
-//
-// Driver Consumed Protocol Prototypes
-//
-//@MT:#include EFI_PROTOCOL_CONSUMER (Ip4)
-//@MT:#include EFI_PROTOCOL_CONSUMER (Udp4)
#define EFI_IP4_HEADER_LEN(HdrPtr) ((HdrPtr)->HeaderLength << 2)
#include <Protocol/DriverConfiguration.h>
#include <Protocol/DriverDiagnostics.h>
-#define EFI_NET_LITTLE_ENDIAN
-
-typedef UINT32 IP4_ADDR;
-typedef UINT32 TCP_SEQNO;
-typedef UINT16 TCP_PORTNO;
-
-enum {
- NET_ETHER_ADDR_LEN = 6,
- NET_IFTYPE_ETHERNET = 0x01,
-
- EFI_IP_PROTO_UDP = 0x11,
- EFI_IP_PROTO_TCP = 0x06,
- EFI_IP_PROTO_ICMP = 0x01,
-
- //
- // The address classfication
- //
- IP4_ADDR_CLASSA = 1,
- IP4_ADDR_CLASSB,
- IP4_ADDR_CLASSC,
- IP4_ADDR_CLASSD,
- IP4_ADDR_CLASSE,
-
- IP4_MASK_NUM = 33,
-};
-
-#pragma pack(1)
-
-//
-// Ethernet head definition
-//
-typedef struct {
- UINT8 DstMac [NET_ETHER_ADDR_LEN];
- UINT8 SrcMac [NET_ETHER_ADDR_LEN];
- UINT16 EtherType;
-} ETHER_HEAD;
-
-
-//
-// The EFI_IP4_HEADER is hard to use because the source and
-// destination address are defined as EFI_IPv4_ADDRESS, which
-// is a structure. Two structures can't be compared or masked
-// directly. This is why there is an internal representation.
-//
-typedef struct {
-#ifdef EFI_NET_LITTLE_ENDIAN
- UINT8 HeadLen : 4;
- UINT8 Ver : 4;
-#else
- UINT8 Ver : 4;
- UINT8 HeadLen : 4;
-#endif
- UINT8 Tos;
- UINT16 TotalLen;
- UINT16 Id;
- UINT16 Fragment;
- UINT8 Ttl;
- UINT8 Protocol;
- UINT16 Checksum;
- IP4_ADDR Src;
- IP4_ADDR Dst;
-} IP4_HEAD;
-
-
-//
-// ICMP head definition. ICMP message is categoried as either an error
-// message or query message. Two message types have their own head format.
-//
-typedef struct {
- UINT8 Type;
- UINT8 Code;
- UINT16 Checksum;
-} IP4_ICMP_HEAD;
-
-typedef struct {
- IP4_ICMP_HEAD Head;
- UINT32 Fourth; // 4th filed of the head, it depends on Type.
- IP4_HEAD IpHead;
-} IP4_ICMP_ERROR_HEAD;
-
-typedef struct {
- IP4_ICMP_HEAD Head;
- UINT16 Id;
- UINT16 Seq;
-} IP4_ICMP_QUERY_HEAD;
-
-
-//
-// UDP header definition
-//
-typedef struct {
- UINT16 SrcPort;
- UINT16 DstPort;
- UINT16 Length;
- UINT16 Checksum;
-} EFI_UDP4_HEADER;
-
-
-//
-// TCP header definition
-//
-typedef struct {
- TCP_PORTNO SrcPort;
- TCP_PORTNO DstPort;
- TCP_SEQNO Seq;
- TCP_SEQNO Ack;
-#ifdef EFI_NET_LITTLE_ENDIAN
- UINT8 Res : 4;
- UINT8 HeadLen : 4;
-#else
- UINT8 HeadLen : 4;
- UINT8 Res : 4;
-#endif
- UINT8 Flag;
- UINT16 Wnd;
- UINT16 Checksum;
- UINT16 Urg;
-} TCP_HEAD;
-
-#pragma pack()
-
-#define NET_MAC_EQUAL(pMac1, pMac2, Len) \
- (NetCompareMem ((pMac1), (pMac2), Len) == 0)
-
-#define NET_MAC_IS_MULTICAST(Mac, BMac, Len) \
- (((*((UINT8 *) Mac) & 0x01) == 0x01) && (!NET_MAC_EQUAL (Mac, BMac, Len)))
-
-#ifdef EFI_NET_LITTLE_ENDIAN
-#define NTOHL(x) (UINT32)((((UINT32) (x) & 0xff) << 24) | \
- (((UINT32) (x) & 0xff00) << 8) | \
- (((UINT32) (x) & 0xff0000) >> 8) | \
- (((UINT32) (x) & 0xff000000) >> 24))
-
-#define HTONL(x) NTOHL(x)
-
-#define NTOHS(x) (UINT16)((((UINT16) (x) & 0xff) << 8) | \
- (((UINT16) (x) & 0xff00) >> 8))
-
-#define HTONS(x) NTOHS(x)
-#else
-#define NTOHL(x) (UINT32)(x)
-#define HTONL(x) (UINT32)(x)
-#define NTOHS(x) (UINT16)(x)
-#define HTONS(x) (UINT16)(x)
-#endif
-
-//
-// Test the IP's attribute, All the IPs are in host byte order.
-//
-#define IP4_IS_MULTICAST(Ip) (((Ip) & 0xF0000000) == 0xE0000000)
-#define IP4_IS_LOCAL_BROADCAST(Ip) ((Ip) == 0xFFFFFFFF)
-#define IP4_NET_EQUAL(Ip1, Ip2, NetMask) (((Ip1) & (NetMask)) == ((Ip2) & (NetMask)))
-#define IP4_IS_VALID_NETMASK(Ip) (NetGetMaskLength (Ip) != IP4_MASK_NUM)
-
-//
-// Convert the EFI_IP4_ADDRESS to plain UINT32 IP4 address.
-//
-#define EFI_IP4(EfiIpAddr) (*(IP4_ADDR *) ((EfiIpAddr).Addr))
-#define EFI_NTOHL(EfiIp) (NTOHL (EFI_IP4 ((EfiIp))))
-#define EFI_IP_EQUAL(Ip1, Ip2) (EFI_IP4 (Ip1) == EFI_IP4 (Ip2))
-
-INTN
-NetGetMaskLength (
- IN IP4_ADDR Mask
- );
-
-INTN
-NetGetIpClass (
- IN IP4_ADDR Addr
- );
-
-BOOLEAN
-Ip4IsUnicast (
- IN IP4_ADDR Ip,
- IN IP4_ADDR NetMask
- );
-
+#define EFI_NET_LITTLE_ENDIAN\r
+\r
+typedef UINT32 IP4_ADDR;\r
+typedef UINT32 TCP_SEQNO;\r
+typedef UINT16 TCP_PORTNO;\r
+\r
+enum {\r
+ NET_ETHER_ADDR_LEN = 6,\r
+ NET_IFTYPE_ETHERNET = 0x01,\r
+\r
+ EFI_IP_PROTO_UDP = 0x11,\r
+ EFI_IP_PROTO_TCP = 0x06,\r
+ EFI_IP_PROTO_ICMP = 0x01,\r
+\r
+ //\r
+ // The address classfication\r
+ //\r
+ IP4_ADDR_CLASSA = 1,\r
+ IP4_ADDR_CLASSB,\r
+ IP4_ADDR_CLASSC,\r
+ IP4_ADDR_CLASSD,\r
+ IP4_ADDR_CLASSE,\r
+\r
+ IP4_MASK_NUM = 33,\r
+};\r
+\r
+#pragma pack(1)\r
+\r
+//\r
+// Ethernet head definition\r
+//\r
+typedef struct {\r
+ UINT8 DstMac [NET_ETHER_ADDR_LEN];\r
+ UINT8 SrcMac [NET_ETHER_ADDR_LEN];\r
+ UINT16 EtherType;\r
+} ETHER_HEAD;\r
+\r
+\r
+//\r
+// The EFI_IP4_HEADER is hard to use because the source and\r
+// destination address are defined as EFI_IPv4_ADDRESS, which\r
+// is a structure. Two structures can't be compared or masked\r
+// directly. This is why there is an internal representation.\r
+//\r
+typedef struct {\r
+#ifdef EFI_NET_LITTLE_ENDIAN\r
+ UINT8 HeadLen : 4;\r
+ UINT8 Ver : 4;\r
+#else\r
+ UINT8 Ver : 4;\r
+ UINT8 HeadLen : 4;\r
+#endif\r
+ UINT8 Tos;\r
+ UINT16 TotalLen;\r
+ UINT16 Id;\r
+ UINT16 Fragment;\r
+ UINT8 Ttl;\r
+ UINT8 Protocol;\r
+ UINT16 Checksum;\r
+ IP4_ADDR Src;\r
+ IP4_ADDR Dst;\r
+} IP4_HEAD;\r
+\r
+\r
+//\r
+// ICMP head definition. ICMP message is categoried as either an error\r
+// message or query message. Two message types have their own head format.\r
+//\r
+typedef struct {\r
+ UINT8 Type;\r
+ UINT8 Code;\r
+ UINT16 Checksum;\r
+} IP4_ICMP_HEAD;\r
+\r
+typedef struct {\r
+ IP4_ICMP_HEAD Head;\r
+ UINT32 Fourth; // 4th filed of the head, it depends on Type.\r
+ IP4_HEAD IpHead;\r
+} IP4_ICMP_ERROR_HEAD;\r
+\r
+typedef struct {\r
+ IP4_ICMP_HEAD Head;\r
+ UINT16 Id;\r
+ UINT16 Seq;\r
+} IP4_ICMP_QUERY_HEAD;\r
+\r
+\r
+//\r
+// UDP header definition\r
+//\r
+typedef struct {\r
+ UINT16 SrcPort;\r
+ UINT16 DstPort;\r
+ UINT16 Length;\r
+ UINT16 Checksum;\r
+} EFI_UDP4_HEADER;\r
+\r
+\r
+//\r
+// TCP header definition\r
+//\r
+typedef struct {\r
+ TCP_PORTNO SrcPort;\r
+ TCP_PORTNO DstPort;\r
+ TCP_SEQNO Seq;\r
+ TCP_SEQNO Ack;\r
+#ifdef EFI_NET_LITTLE_ENDIAN\r
+ UINT8 Res : 4;\r
+ UINT8 HeadLen : 4;\r
+#else\r
+ UINT8 HeadLen : 4;\r
+ UINT8 Res : 4;\r
+#endif\r
+ UINT8 Flag;\r
+ UINT16 Wnd;\r
+ UINT16 Checksum;\r
+ UINT16 Urg;\r
+} TCP_HEAD;\r
+\r
+#pragma pack()\r
+\r
+#define NET_MAC_EQUAL(pMac1, pMac2, Len) \\r
+ (NetCompareMem ((pMac1), (pMac2), Len) == 0)\r
+\r
+#define NET_MAC_IS_MULTICAST(Mac, BMac, Len) \\r
+ (((*((UINT8 *) Mac) & 0x01) == 0x01) && (!NET_MAC_EQUAL (Mac, BMac, Len)))\r
+\r
+#ifdef EFI_NET_LITTLE_ENDIAN\r
+#define NTOHL(x) (UINT32)((((UINT32) (x) & 0xff) << 24) | \\r
+ (((UINT32) (x) & 0xff00) << 8) | \\r
+ (((UINT32) (x) & 0xff0000) >> 8) | \\r
+ (((UINT32) (x) & 0xff000000) >> 24))\r
+\r
+#define HTONL(x) NTOHL(x)\r
+\r
+#define NTOHS(x) (UINT16)((((UINT16) (x) & 0xff) << 8) | \\r
+ (((UINT16) (x) & 0xff00) >> 8))\r
+\r
+#define HTONS(x) NTOHS(x)\r
+#else\r
+#define NTOHL(x) (UINT32)(x)\r
+#define HTONL(x) (UINT32)(x)\r
+#define NTOHS(x) (UINT16)(x)\r
+#define HTONS(x) (UINT16)(x)\r
+#endif\r
+\r
+//\r
+// Test the IP's attribute, All the IPs are in host byte order.\r
+//\r
+#define IP4_IS_MULTICAST(Ip) (((Ip) & 0xF0000000) == 0xE0000000)\r
+#define IP4_IS_LOCAL_BROADCAST(Ip) ((Ip) == 0xFFFFFFFF)\r
+#define IP4_NET_EQUAL(Ip1, Ip2, NetMask) (((Ip1) & (NetMask)) == ((Ip2) & (NetMask)))\r
+#define IP4_IS_VALID_NETMASK(Ip) (NetGetMaskLength (Ip) != IP4_MASK_NUM)\r
+\r
+//\r
+// Convert the EFI_IP4_ADDRESS to plain UINT32 IP4 address.\r
+//\r
+#define EFI_IP4(EfiIpAddr) (*(IP4_ADDR *) ((EfiIpAddr).Addr))\r
+#define EFI_NTOHL(EfiIp) (NTOHL (EFI_IP4 ((EfiIp))))\r
+#define EFI_IP4_EQUAL(Ip1, Ip2) (NetCompareMem (&(Ip1), &(Ip2), sizeof (EFI_IPv4_ADDRESS)) == 0)\r
+\r
+INTN\r
+NetGetMaskLength (\r
+ IN IP4_ADDR Mask\r
+ );\r
+\r
+INTN\r
+NetGetIpClass (\r
+ IN IP4_ADDR Addr\r
+ );\r
+\r
+BOOLEAN\r
+Ip4IsUnicast (\r
+ IN IP4_ADDR Ip,\r
+ IN IP4_ADDR NetMask\r
+ );\r
+\r
extern IP4_ADDR mIp4AllMasks [IP4_MASK_NUM];
-//@MT:#include EFI_PROTOCOL_CONSUMER (LoadedImage)
-//@MT:#include EFI_PROTOCOL_CONSUMER (ServiceBinding)
-//@MT:#include EFI_PROTOCOL_CONSUMER (SimpleNetwork)
+extern EFI_IPv4_ADDRESS mZeroIp4Addr;
+
+#define NET_IS_DIGIT(Ch) (('0' <= (Ch)) && ((Ch) <= '9'))
//
// Wrap functions to ease the impact of EFI library changes.
//
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+ PxeDhcp4.h\r
+\r
+Abstract:\r
+ EFI PXE DHCPv4 protocol definition\r
+\r
+--*/\r
+\r
+#ifndef _PXEDHCP4_H_\r
+#define _PXEDHCP4_H_\r
+\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+//\r
+// PXE DHCPv4 GUID definition\r
+//\r
+\r
+#define EFI_PXE_DHCP4_PROTOCOL_GUID \\r
+ { 0x03c4e624, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x29, 0x3f, 0xc1, 0x4d } }\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+//\r
+// Interface definition\r
+//\r
+\r
+typedef struct _EFI_PXE_DHCP4_PROTOCOL EFI_PXE_DHCP4_PROTOCOL;\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+//\r
+// Descriptions of the DHCP version 4 header and options can be found\r
+// in RFC-2131 and RFC-2132 at www.ietf.org\r
+//\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+\r
+ UINT8 op;\r
+#define BOOTP_REQUEST 1\r
+#define BOOTP_REPLY 2\r
+\r
+ UINT8 htype;\r
+\r
+ UINT8 hlen;\r
+\r
+ UINT8 hops;\r
+\r
+ UINT32 xid;\r
+\r
+ UINT16 secs;\r
+#define DHCP4_INITIAL_SECONDS 4\r
+\r
+ UINT16 flags;\r
+#define DHCP4_BROADCAST_FLAG 0x8000\r
+\r
+ UINT32 ciaddr;\r
+\r
+ UINT32 yiaddr;\r
+\r
+ UINT32 siaddr;\r
+\r
+ UINT32 giaddr;\r
+\r
+ UINT8 chaddr[16];\r
+\r
+ UINT8 sname[64];\r
+\r
+ UINT8 fname[128];\r
+\r
+//\r
+// This is the minimum option length as specified in RFC-2131.\r
+// The packet must be padded out this far with DHCP4_PAD.\r
+// DHCPv4 packets are usually 576 bytes in length. This length\r
+// includes the IPv4 and UDPv4 headers but not the media header.\r
+// Note: Not all DHCP relay agents will forward DHCPv4 packets\r
+// if they are less than 384 bytes or exceed 576 bytes. Even if\r
+// the underlying hardware can handle smaller and larger packets,\r
+// many older relay agents will not accept them.\r
+//\r
+ UINT32 magik;\r
+#define DHCP4_MAGIK_NUMBER 0x63825363\r
+\r
+ UINT8 options[308];\r
+\r
+} DHCP4_HEADER;\r
+#pragma pack()\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+//\r
+// DHCPv4 packet definition. Room for 576 bytes including IP and\r
+// UDP header.\r
+//\r
+\r
+#define DHCP4_MAX_PACKET_SIZE 576\r
+#define DHCP4_UDP_HEADER_SIZE 8\r
+#define DHCP4_IP_HEADER_SIZE 20\r
+\r
+#pragma pack(1)\r
+typedef union _DHCP4_PACKET {\r
+ UINT32 _force_data_alignment;\r
+\r
+ UINT8 raw[1500];\r
+\r
+ DHCP4_HEADER dhcp4;\r
+} DHCP4_PACKET;\r
+#pragma pack()\r
+\r
+#define DHCP4_SERVER_PORT 67\r
+#define DHCP4_CLIENT_PORT 68\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+//\r
+// DHCPv4 and PXE option numbers.\r
+//\r
+\r
+#define DHCP4_PAD 0\r
+#define DHCP4_END 255\r
+#define DHCP4_SUBNET_MASK 1\r
+#define DHCP4_TIME_OFFSET 2\r
+#define DHCP4_ROUTER_LIST 3\r
+#define DHCP4_TIME_SERVERS 4\r
+#define DHCP4_NAME_SERVERS 5\r
+#define DHCP4_DNS_SERVERS 6\r
+#define DHCP4_LOG_SERVERS 7\r
+#define DHCP4_COOKIE_SERVERS 8\r
+#define DHCP4_LPR_SREVERS 9\r
+#define DHCP4_IMPRESS_SERVERS 10\r
+#define DHCP4_RESOURCE_LOCATION_SERVERS 11\r
+#define DHCP4_HOST_NAME 12\r
+#define DHCP4_BOOT_FILE_SIZE 13\r
+#define DHCP4_DUMP_FILE 14\r
+#define DHCP4_DOMAIN_NAME 15\r
+#define DHCP4_SWAP_SERVER 16\r
+#define DHCP4_ROOT_PATH 17\r
+#define DHCP4_EXTENSION_PATH 18\r
+#define DHCP4_IP_FORWARDING 19\r
+#define DHCP4_NON_LOCAL_SOURCE_ROUTE 20\r
+#define DHCP4_POLICY_FILTER 21\r
+#define DHCP4_MAX_DATAGRAM_SIZE 22\r
+#define DHCP4_DEFAULT_TTL 23\r
+#define DHCP4_MTU_AGING_TIMEOUT 24\r
+#define DHCP4_MTU_SIZES 25\r
+#define DHCP4_MTU_TO_USE 26\r
+#define DHCP4_ALL_SUBNETS_LOCAL 27\r
+#define DHCP4_BROADCAST_ADDRESS 28\r
+#define DHCP4_PERFORM_MASK_DISCOVERY 29\r
+#define DHCP4_RESPOND_TO_MASK_REQ 30\r
+#define DHCP4_PERFORM_ROUTER_DISCOVERY 31\r
+#define DHCP4_ROUTER_SOLICIT_ADDRESS 32\r
+#define DHCP4_STATIC_ROUTER_LIST 33\r
+#define DHCP4_USE_ARP_TRAILERS 34\r
+#define DHCP4_ARP_CACHE_TIMEOUT 35\r
+#define DHCP4_ETHERNET_ENCAPSULATION 36\r
+#define DHCP4_TCP_DEFAULT_TTL 37\r
+#define DHCP4_TCP_KEEP_ALIVE_INT 38\r
+#define DHCP4_KEEP_ALIVE_GARBAGE 39\r
+#define DHCP4_NIS_DOMAIN_NAME 40\r
+#define DHCP4_NIS_SERVERS 41\r
+#define DHCP4_NTP_SERVERS 42\r
+#define DHCP4_VENDOR_SPECIFIC 43\r
+# define PXE_MTFTP_IP 1\r
+# define PXE_MTFTP_CPORT 2\r
+# define PXE_MTFTP_SPORT 3\r
+# define PXE_MTFTP_TMOUT 4\r
+# define PXE_MTFTP_DELAY 5\r
+# define PXE_DISCOVERY_CONTROL 6\r
+# define PXE_DISABLE_BROADCAST_DISCOVERY 0x01\r
+# define PXE_DISABLE_MULTICAST_DISCOVERY 0x02\r
+# define PXE_ACCEPT_ONLY_PXE_BOOT_SERVERS 0x04\r
+# define PXE_DO_NOT_PROMPT 0x08\r
+# define PXE_DISCOVERY_MCAST_ADDR 7\r
+# define PXE_BOOT_SERVERS 8\r
+# define PXE_BOOT_MENU 9\r
+# define PXE_BOOT_PROMPT 10\r
+# define PXE_MCAST_ADDRS_ALLOC 11\r
+# define PXE_CREDENTIAL_TYPES 12\r
+# define PXE_BOOT_ITEM 71\r
+#define DHCP4_NBNS_SERVERS 44\r
+#define DHCP4_NBDD_SERVERS 45\r
+#define DHCP4_NETBIOS_NODE_TYPE 46\r
+#define DHCP4_NETBIOS_SCOPE 47\r
+#define DHCP4_XWINDOW_SYSTEM_FONT_SERVERS 48\r
+#define DHCP4_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49\r
+#define DHCP4_REQUESTED_IP_ADDRESS 50\r
+#define DHCP4_LEASE_TIME 51\r
+#define DHCP4_OPTION_OVERLOAD 52\r
+# define DHCP4_OVERLOAD_FNAME 1\r
+# define DHCP4_OVERLOAD_SNAME 2\r
+# define DHCP4_OVERLOAD_FNAME_AND_SNAME 3\r
+#define DHCP4_MESSAGE_TYPE 53\r
+# define DHCP4_MESSAGE_TYPE_DISCOVER 1\r
+# define DHCP4_MESSAGE_TYPE_OFFER 2\r
+# define DHCP4_MESSAGE_TYPE_REQUEST 3\r
+# define DHCP4_MESSAGE_TYPE_DECLINE 4\r
+# define DHCP4_MESSAGE_TYPE_ACK 5\r
+# define DHCP4_MESSAGE_TYPE_NAK 6\r
+# define DHCP4_MESSAGE_TYPE_RELEASE 7\r
+# define DHCP4_MESSAGE_TYPE_INFORM 8\r
+#define DHCP4_SERVER_IDENTIFIER 54\r
+#define DHCP4_PARAMETER_REQUEST_LIST 55\r
+#define DHCP4_ERROR_MESSAGE 56\r
+#define DHCP4_MAX_MESSAGE_SIZE 57\r
+# define DHCP4_DEFAULT_MAX_MESSAGE_SIZE 576\r
+#define DHCP4_RENEWAL_TIME 58\r
+#define DHCP4_REBINDING_TIME 59\r
+#define DHCP4_CLASS_IDENTIFIER 60\r
+#define DHCP4_CLIENT_IDENTIFIER 61\r
+#define DHCP4_NISPLUS_DOMAIN_NAME 64\r
+#define DHCP4_NISPLUS_SERVERS 65\r
+#define DHCP4_TFTP_SERVER_NAME 66\r
+#define DHCP4_BOOTFILE 67\r
+#define DHCP4_MOBILE_IP_HOME_AGENTS 68\r
+#define DHCP4_SMPT_SERVERS 69\r
+#define DHCP4_POP3_SERVERS 70\r
+#define DHCP4_NNTP_SERVERS 71\r
+#define DHCP4_WWW_SERVERS 72\r
+#define DHCP4_FINGER_SERVERS 73\r
+#define DHCP4_IRC_SERVERS 74\r
+#define DHCP4_STREET_TALK_SERVERS 75\r
+#define DHCP4_STREET_TALK_DIR_ASSIST_SERVERS 76\r
+#define DHCP4_NDS_SERVERS 85\r
+#define DHCP4_NDS_TREE_NAME 86\r
+#define DHCP4_NDS_CONTEXT 87\r
+#define DHCP4_SYSTEM_ARCHITECTURE 93\r
+#define DHCP4_NETWORK_ARCHITECTURE 94\r
+#define DHCP4_PLATFORM_ID 97\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+//\r
+// DHCP4 option format.\r
+//\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+ UINT8 op;\r
+ UINT8 len;\r
+ UINT8 data[1];\r
+} DHCP4_OP;\r
+#pragma pack()\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+\r
+typedef struct {\r
+ DHCP4_PACKET Discover;\r
+ DHCP4_PACKET Offer;\r
+ DHCP4_PACKET Request;\r
+ DHCP4_PACKET AckNak;\r
+ BOOLEAN SetupCompleted;\r
+ BOOLEAN InitCompleted;\r
+ BOOLEAN SelectCompleted;\r
+ BOOLEAN IsBootp;\r
+ BOOLEAN IsAck;\r
+} EFI_PXE_DHCP4_DATA;\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_RUN) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL *This,\r
+ IN OPTIONAL UINTN OpLen,\r
+ IN OPTIONAL VOID *OpList\r
+ );\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_SETUP) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL *This,\r
+ IN OPTIONAL EFI_PXE_DHCP4_DATA * NewData\r
+ );\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_INIT) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL *This,\r
+ IN UINTN SecondsTimeout,\r
+ OUT UINTN *Offers,\r
+ OUT DHCP4_PACKET **OfferList\r
+ );\r
+\r
+#define DHCP4_MIN_SECONDS 1\r
+#define DHCP4_MAX_SECONDS 60\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_SELECT) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL *This,\r
+ IN UINTN SecondsTimeout,\r
+ IN DHCP4_PACKET * offer\r
+ );\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_RENEW) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL *This,\r
+ UINTN seconds_timeout\r
+ );\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_REBIND) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL *This,\r
+ UINTN seconds_timeout\r
+ );\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_RELEASE) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL * This\r
+ );\r
+\r
+/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
+\r
+#define EFI_PXE_DHCP4_PROTOCOL_REVISION 0x00010000\r
+\r
+struct _EFI_PXE_DHCP4_PROTOCOL {\r
+ UINT64 Revision;\r
+ EFI_PXE_DHCP4_RUN Run;\r
+ EFI_PXE_DHCP4_SETUP Setup;\r
+ EFI_PXE_DHCP4_INIT Init;\r
+ EFI_PXE_DHCP4_SELECT Select;\r
+ EFI_PXE_DHCP4_RENEW Renew;\r
+ EFI_PXE_DHCP4_REBIND Rebind;\r
+ EFI_PXE_DHCP4_RELEASE Release;\r
+ EFI_PXE_DHCP4_DATA *Data;\r
+};\r
+\r
+//\r
+//\r
+//\r
+\r
+extern EFI_GUID gEfiPxeDhcp4ProtocolGuid;\r
+\r
+#endif /* _PXEDHCP4_H_ */\r
+/* EOF - PxeDhcp4.h */\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+ PxeDhcp4Callback.h\r
+\r
+Abstract:\r
+ EFI PXE DHCP4 Callback protocol definition.\r
+\r
+--*/\r
+\r
+#ifndef _PXE_DHCP4CALLBACK_H\r
+#define _PXE_DHCP4CALLBACK_H\r
+\r
+#include <Protocol/PxeDhcp4.h>\r
+//\r
+// GUID definition\r
+//\r
+\r
+#define EFI_PXE_DHCP4_CALLBACK_PROTOCOL_GUID \\r
+{ 0xc1544c01, 0x92a4, 0x4198, {0x8a, 0x84, 0x77, 0x85, 0x83, 0xc2, 0x36, 0x21 } }\r
+\r
+\r
+//\r
+// Revision number\r
+//\r
+\r
+#define EFI_PXE_DHCP4_CALLBACK_INTERFACE_REVISION 0x00010000\r
+\r
+//\r
+// Interface definition\r
+//\r
+\r
+typedef struct _EFI_PXE_DHCP4_CALLBACK_PROTOCOL EFI_PXE_DHCP4_CALLBACK_PROTOCOL;\r
+\r
+typedef enum {\r
+ EFI_PXE_DHCP4_FUNCTION_FIRST,\r
+ EFI_PXE_DHCP4_FUNCTION_INIT,\r
+ EFI_PXE_DHCP4_FUNCTION_SELECT,\r
+ EFI_PXE_DHCP4_FUNCTION_RENEW,\r
+ EFI_PXE_DHCP4_FUNCTION_REBIND,\r
+ EFI_PXE_DHCP4_FUNCTION_LAST\r
+} EFI_PXE_DHCP4_FUNCTION;\r
+\r
+typedef enum {\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_FIRST,\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_ABORT,\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_ABORT,\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_ABORT,\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE,\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_CONTINUE,\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE,\r
+ EFI_PXE_DHCP4_CALLBACK_STATUS_LAST\r
+} EFI_PXE_DHCP4_CALLBACK_STATUS;\r
+\r
+typedef\r
+EFI_PXE_DHCP4_CALLBACK_STATUS\r
+(EFIAPI *EFI_PXE_DHCP4_CALLBACK) (\r
+ IN EFI_PXE_DHCP4_PROTOCOL *This,\r
+ IN EFI_PXE_DHCP4_FUNCTION Function,\r
+ IN UINT32 PacketLen,\r
+ IN DHCP4_PACKET *Packet OPTIONAL\r
+ );\r
+\r
+struct _EFI_PXE_DHCP4_CALLBACK_PROTOCOL {\r
+ UINT64 Revision;\r
+ EFI_PXE_DHCP4_CALLBACK Callback;\r
+};\r
+\r
+//\r
+// GUID declaration\r
+//\r
+\r
+extern EFI_GUID gEfiPxeDhcp4CallbackProtocolGuid;\r
+\r
+#endif /* _PXE_DHCP4CALLBACK_H */\r
+/* EOF - PxeDhcp4Callback.h */\r
--- /dev/null
+/*++\r
+\r
+Copyright (c) 2004, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ tcp.h\r
+\r
+Abstract:\r
+\r
+ EFI Transmission Control Protocol\r
+\r
+\r
+\r
+Revision History\r
+\r
+--*/\r
+\r
+\r
+#ifndef _EFITCP_H\r
+#define _EFITCP_H\r
+\r
+\r
+#include <Protocol/PxeBaseCode.h>\r
+\r
+//\r
+// PXE Base Code protocol\r
+//\r
+\r
+#define EFI_TCP_PROTOCOL_GUID \\r
+ { 0x02b3d5f2, 0xac28, 0x11d3, { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }}\r
+\r
+\r
+typedef UINT16 EFI_PXE_BASE_CODE_TCP_PORT;\r
+\r
+//\r
+// Port Receive Filter definitions\r
+//\r
+#define EFI_PXE_BASE_CODE_MAX_PORTCNT 8\r
+typedef struct {\r
+ UINT8 Filters;\r
+ UINT8 IpCnt;\r
+ UINT16 reserved;\r
+ EFI_IP_ADDRESS IpList[EFI_PXE_BASE_CODE_MAX_PORTCNT];\r
+} EFI_TCP_PORT_FILTER;\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_TCP_WRITE) (\r
+ IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
+ IN UINT16 OpFlags,\r
+ IN UINT16 *UrgentPointer,\r
+ IN UINT32 *SequenceNumber,\r
+ IN UINT32 *AckNumber,\r
+ IN UINT16 *HlenResCode,\r
+ IN UINT16 *Window,\r
+ IN EFI_IP_ADDRESS *DestIp,\r
+ IN UINT16 *DestPort,\r
+ IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL\r
+ IN EFI_IP_ADDRESS *SrcIp, OPTIONAL\r
+ IN UINT16 *SrcPort, OPTIONAL\r
+ IN UINTN *HeaderSize, OPTIONAL\r
+ IN VOID *HeaderPtr, OPTIONAL\r
+ IN UINTN *BufferSize,\r
+ IN VOID *BufferPtr\r
+ );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_TCP_READ) (\r
+ IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
+ IN UINT16 OpFlags,\r
+ IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL\r
+ IN OUT UINT16 *DestPort, OPTIONAL\r
+ IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL\r
+ IN OUT UINT16 *SrcPort, OPTIONAL\r
+ IN UINTN *HeaderSize, OPTIONAL\r
+ IN VOID *HeaderPtr, OPTIONAL\r
+ IN OUT UINTN *BufferSize,\r
+ IN VOID *BufferPtr\r
+ );\r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *EFI_TCP_SET_PORT_FILTER) (\r
+ IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
+ IN EFI_TCP_PORT_FILTER *NewFilter\r
+ );\r
+\r
+//\r
+// TCP Protocol structure\r
+//\r
+typedef struct _EFI_TCP_PROTOCOL {\r
+ EFI_TCP_WRITE TcpWrite;\r
+ EFI_TCP_READ TcpRead;\r
+ EFI_TCP_SET_PORT_FILTER SetPortFilter;\r
+} EFI_TCP_PROTOCOL;\r
+\r
+extern EFI_GUID gEfiTcpProtocolGuid;\r
+\r
+#endif /* _EFITCP_H */\r
0xFFFFFFFF,
};
+EFI_IPv4_ADDRESS mZeroIp4Addr = {0, 0, 0, 0};
/**\r
Converts the low nibble of a byte to hex unicode character.\r
gEfiNicIp4ConfigProtocolGuid = {0xdca3d4d, 0x12da, 0x4728, { 0xbf, 0x7e, 0x86, 0xce, 0xb9, 0x28, 0xd0, 0x67 }}\r
gEfiNicIp4ConfigVariableGuid = {0xd8944553, 0xc4dd, 0x41f4, { 0x9b, 0x30, 0xe1, 0x39, 0x7c, 0xfb, 0x26, 0x7b }}\r
\r
+ gEfiTcpProtocolGuid = { 0x02b3d5f2, 0xac28, 0x11d3, { 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d }}\r
+ gEfiPxeDhcp4CallbackProtocolGuid = { 0xc1544c01, 0x92a4, 0x4198, {0x8a, 0x84, 0x77, 0x85, 0x83, 0xc2, 0x36, 0x21 } }\r
+ gEfiPxeDhcp4ProtocolGuid = { 0x03c4e624, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x29, 0x3f, 0xc1, 0x4d } }\r
+\r
[Ppis.common]\r
gPeiBaseMemoryTestPpiGuid = { 0xB6EC423C, 0x21D2, 0x490D, { 0x85, 0xC6, 0xDD, 0x58, 0x64, 0xEA, 0xA6, 0x74 }}\r
\r
[LibraryClasses.IPF]\r
IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf\r
\r
-[LibraryClasses.EBC.DXE_RUNTIME_DRIVER]\r
+[LibraryClasses.EBC]\r
IoLib|IntelFrameworkPkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.inf\r
\r
[LibraryClasses.common.PEI_CORE]\r
UsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf\r
NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf\r
IpIoLib|MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf\r
+ UdpIoLib|MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf\r
\r
[LibraryClasses.common.DXE_RUNTIME_DRIVER]\r
HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf\r
MdeModulePkg/Library/DxeIpIoLib/DxeIpIoLib.inf\r
MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.inf\r
\r
+ MdeModulePkg/Universal/Network/ArpDxe/ArpDxe.inf\r
+ MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Dxe.inf\r
MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4ConfigDxe.inf\r
+ MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Dxe.inf\r
MdeModulePkg/Universal/Network/MnpDxe/MnpDxe.inf\r
+ MdeModulePkg/Universal/Network/PxeBcDxe/PxeBcDxe.inf\r
+ MdeModulePkg/Universal/Network/PxeDhcp4Dxe/PxeDhcp4Dxe.inf\r
MdeModulePkg/Universal/Network/SnpDxe/SnpDxe.inf\r
MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Dxe.inf\r
MdeModulePkg/Universal/Network/Udp4Dxe/Udp4Dxe.inf\r
--- /dev/null
+/** @file
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. 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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpDebug.h
+
+Abstract:
+
+
+**/
+
+#ifndef _ARP_DEBUG_H_
+#define _ARP_DEBUG_H_
+
+
+#define ARP_DEBUG_TRACE(PrintArg) NET_DEBUG_TRACE ("Arp", PrintArg)
+#define ARP_DEBUG_WARN(PrintArg) NET_DEBUG_WARNING ("Arp", PrintArg)
+#define ARP_DEBUG_ERROR(PrintArg) NET_DEBUG_ERROR ("Arp", PrintArg)
+
+#endif
+
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ ArpDriver.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+\r
+#include "ArpDriver.h"\r
+#include "ArpImpl.h"\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding = {\r
+ ArpDriverBindingSupported,\r
+ ArpDriverBindingStart,\r
+ ArpDriverBindingStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+\r
+/**\r
+ Create and initialize the arp service context data.\r
+\r
+ @param ImageHandle The image handle representing the loaded driver\r
+ image.\r
+ @param ControllerHandle The controller handle the driver binds to.\r
+ @param ArpService Pointer to the buffer containing the arp service\r
+ context data.\r
+\r
+ @retval EFI_SUCCESS The arp service context is initialized.\r
+ @retval other Failed to initialize the arp service context.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+ArpCreateService (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN ARP_SERVICE_DATA *ArpService\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (ArpService != NULL);\r
+\r
+ ArpService->Signature = ARP_SERVICE_DATA_SIGNATURE;\r
+\r
+ //\r
+ // Init the servicebinding protocol members.\r
+ //\r
+ ArpService->ServiceBinding.CreateChild = ArpServiceBindingCreateChild;\r
+ ArpService->ServiceBinding.DestroyChild = ArpServiceBindingDestroyChild;\r
+\r
+ //\r
+ // Save the handles.\r
+ //\r
+ ArpService->ImageHandle = ImageHandle;\r
+ ArpService->ControllerHandle = ControllerHandle;\r
+\r
+ //\r
+ // Create a MNP child instance.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ ImageHandle,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ &ArpService->MnpChildHandle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Open the MNP protocol.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ArpService->MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ (VOID **)&ArpService->Mnp,\r
+ ImageHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_EXIT;\r
+ }\r
+\r
+ //\r
+ // Get the underlayer Snp mode data.\r
+ //\r
+ Status = ArpService->Mnp->GetModeData (ArpService->Mnp, NULL, &ArpService->SnpMode);\r
+ if ((Status != EFI_NOT_STARTED) && EFI_ERROR (Status)) {\r
+ goto ERROR_EXIT;\r
+ }\r
+\r
+ if (ArpService->SnpMode.IfType != NET_IFTYPE_ETHERNET) {\r
+ //\r
+ // Only support the ethernet.\r
+ //\r
+ Status = EFI_UNSUPPORTED;\r
+ goto ERROR_EXIT;\r
+ }\r
+\r
+ //\r
+ // Set the Mnp config parameters.\r
+ //\r
+ ArpService->MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
+ ArpService->MnpConfigData.TransmitQueueTimeoutValue = 0;\r
+ ArpService->MnpConfigData.ProtocolTypeFilter = ARP_ETHER_PROTO_TYPE;\r
+ ArpService->MnpConfigData.EnableUnicastReceive = TRUE;\r
+ ArpService->MnpConfigData.EnableMulticastReceive = FALSE;\r
+ ArpService->MnpConfigData.EnableBroadcastReceive = TRUE;\r
+ ArpService->MnpConfigData.EnablePromiscuousReceive = FALSE;\r
+ ArpService->MnpConfigData.FlushQueuesOnReset = TRUE;\r
+ ArpService->MnpConfigData.EnableReceiveTimestamps = FALSE;\r
+ ArpService->MnpConfigData.DisableBackgroundPolling = FALSE;\r
+\r
+ //\r
+ // Configure the Mnp child.\r
+ //\r
+ Status = ArpService->Mnp->Configure (ArpService->Mnp, &ArpService->MnpConfigData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_EXIT;\r
+ }\r
+\r
+ //\r
+ // Create the event used in the RxToken.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ NET_TPL_EVENT,\r
+ ArpOnFrameRcvd,\r
+ ArpService,\r
+ &ArpService->RxToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_EXIT;\r
+ }\r
+\r
+ //\r
+ // Create the Arp heartbeat timer.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
+ NET_TPL_TIMER,\r
+ ArpTimerHandler,\r
+ ArpService,\r
+ &ArpService->PeriodicTimer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_EXIT;\r
+ }\r
+\r
+ //\r
+ // Start the heartbeat timer.\r
+ //\r
+ Status = gBS->SetTimer (\r
+ ArpService->PeriodicTimer,\r
+ TimerPeriodic,\r
+ ARP_PERIODIC_TIMER_INTERVAL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_EXIT;\r
+ }\r
+\r
+ //\r
+ // Init the lock.\r
+ //\r
+ NET_LOCK_INIT (&ArpService->Lock);\r
+\r
+ //\r
+ // Init the lists.\r
+ //\r
+ NetListInit (&ArpService->ChildrenList);\r
+ NetListInit (&ArpService->PendingRequestTable);\r
+ NetListInit (&ArpService->DeniedCacheTable);\r
+ NetListInit (&ArpService->ResolvedCacheTable);\r
+\r
+ERROR_EXIT:\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Clean the arp service context data.\r
+\r
+ @param ArpService Pointer to the buffer containing the arp service\r
+ context data.\r
+\r
+ @return None.\r
+\r
+**/\r
+STATIC\r
+VOID\r
+ArpCleanService (\r
+ IN ARP_SERVICE_DATA *ArpService\r
+ )\r
+{\r
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
+\r
+ if (ArpService->PeriodicTimer != NULL) {\r
+ //\r
+ // Cancle and close the PeriodicTimer.\r
+ //\r
+ gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0);\r
+ gBS->CloseEvent (ArpService->PeriodicTimer);\r
+ }\r
+\r
+ if (ArpService->RxToken.Event != NULL) {\r
+ //\r
+ // Cancle the RxToken and close the event in the RxToken.\r
+ //\r
+ ArpService->Mnp->Cancel (ArpService->Mnp, NULL);\r
+ gBS->CloseEvent (ArpService->RxToken.Event);\r
+ }\r
+\r
+ if (ArpService->Mnp != NULL) {\r
+ //\r
+ // Reset the Mnp child and close the Mnp protocol.\r
+ //\r
+ ArpService->Mnp->Configure (ArpService->Mnp, NULL);\r
+ gBS->CloseProtocol (\r
+ ArpService->MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ ArpService->ImageHandle,\r
+ ArpService->ControllerHandle\r
+ );\r
+ }\r
+\r
+ if (ArpService->MnpChildHandle != NULL) {\r
+ //\r
+ // Destroy the mnp child.\r
+ //\r
+ NetLibDestroyServiceChild(\r
+ ArpService->ControllerHandle,\r
+ ArpService->ImageHandle,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ ArpService->MnpChildHandle\r
+ );\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Test to see if this driver supports ControllerHandle.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to test.\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCES This driver supports this device\r
+ @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // Test to see if Arp SB is already installed.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiArpServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (Status == EFI_SUCCESS) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ //\r
+ // Test to see if MNP SB is installed.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Start this driver on ControllerHandle.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to bind driver to\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCES This driver is added to ControllerHandle\r
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
+ @retval other This driver does not support this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_SERVICE_DATA *ArpService;\r
+\r
+ //\r
+ // Allocate a zero pool for ArpService.\r
+ //\r
+ ArpService = NetAllocateZeroPool (sizeof(ARP_SERVICE_DATA));\r
+ if (ArpService == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Initialize the arp service context data.\r
+ //\r
+ Status = ArpCreateService (This->DriverBindingHandle, ControllerHandle, ArpService);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR;\r
+ }\r
+\r
+ //\r
+ // Install the ARP service binding protocol.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ControllerHandle,\r
+ &gEfiArpServiceBindingProtocolGuid,\r
+ &ArpService->ServiceBinding,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR;\r
+ }\r
+\r
+ //\r
+ // OK, start to receive arp packets from Mnp.\r
+ //\r
+ Status = ArpService->Mnp->Receive (ArpService->Mnp, &ArpService->RxToken);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR;\r
+ }\r
+\r
+ return Status;\r
+\r
+ERROR:\r
+\r
+ //\r
+ // On error, clean the arp service context data, and free the memory allocated.\r
+ //\r
+ ArpCleanService (ArpService);\r
+ NetFreePool (ArpService);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop this driver on ControllerHandle.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to stop driver on\r
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
+ of children is zero stop the entire bus driver.\r
+ @param ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+ @retval EFI_SUCCES This driver is removed ControllerHandle\r
+ @retval other This driver was not removed from this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE NicHandle;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ ARP_INSTANCE_DATA *Instance;\r
+\r
+ //\r
+ // Get the NicHandle which the arp servicebinding is installed on.\r
+ //\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
+ if (NicHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Try to get the arp servicebinding protocol on the NicHandle.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ NicHandle,\r
+ &gEfiArpServiceBindingProtocolGuid,\r
+ (VOID **)&ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ARP_DEBUG_ERROR (("ArpDriverBindingStop: Open ArpSb failed, %r.\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ ArpService = ARP_SERVICE_DATA_FROM_THIS (ServiceBinding);\r
+\r
+ while (!NetListIsEmpty (&ArpService->ChildrenList)) {\r
+ //\r
+ // Iterate all the instances.\r
+ //\r
+ Instance = NET_LIST_HEAD (&ArpService->ChildrenList, ARP_INSTANCE_DATA, List);\r
+\r
+ //\r
+ // Destroy this arp child.\r
+ //\r
+ ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
+ }\r
+\r
+ ASSERT (NetListIsEmpty (&ArpService->PendingRequestTable));\r
+ ASSERT (NetListIsEmpty (&ArpService->DeniedCacheTable));\r
+ ASSERT (NetListIsEmpty (&ArpService->ResolvedCacheTable));\r
+\r
+ //\r
+ // Uninstall the ARP ServiceBinding protocol.\r
+ //\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ NicHandle,\r
+ &gEfiArpServiceBindingProtocolGuid,\r
+ &ArpService->ServiceBinding,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ARP_DEBUG_ERROR (("ArpDriverBindingStop: Failed to uninstall ArpSb, %r.\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Clean the arp servicebinding context data and free the memory allocated.\r
+ //\r
+ ArpCleanService (ArpService);\r
+ NetFreePool (ArpService);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Creates a child handle with a set of I/O services.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ChildHandle Pointer to the handle of the child to create. If\r
+ it is NULL, then a new handle is created. If it is\r
+ not NULL, then the I/O services are added to the\r
+ existing child handle.\r
+\r
+ @retval EFI_SUCCES The child handle was created with the I/O\r
+ services.\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
+ the child.\r
+ @retval other The child handle was not created.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpServiceBindingCreateChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE *ChildHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ ARP_INSTANCE_DATA *Instance;\r
+ VOID *Mnp;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Allocate memory for the instance context data.\r
+ //\r
+ Instance = NetAllocateZeroPool (sizeof(ARP_INSTANCE_DATA));\r
+ if (Instance == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpSBCreateChild: Failed to allocate memory for Instance.\n"));\r
+\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Init the instance context data.\r
+ //\r
+ ArpInitInstance (ArpService, Instance);\r
+\r
+ //\r
+ // Install the ARP protocol onto the ChildHandle.\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ ChildHandle,\r
+ &gEfiArpProtocolGuid,\r
+ (VOID *)&Instance->ArpProto,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ARP_DEBUG_ERROR (("ArpSBCreateChild: faild to install ARP protocol, %r.\n", Status));\r
+\r
+ NetFreePool (Instance);\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Save the ChildHandle.\r
+ //\r
+ Instance->Handle = *ChildHandle;\r
+\r
+ //\r
+ // Open the Managed Network protocol BY_CHILD.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ArpService->MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ (VOID **) &Mnp,\r
+ gArpDriverBinding.DriverBindingHandle,\r
+ Instance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR;\r
+ }\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto ERROR;\r
+ }\r
+\r
+ //\r
+ // Insert the instance into children list managed by the arp service context data.\r
+ //\r
+ NetListInsertTail (&ArpService->ChildrenList, &Instance->List);\r
+ ArpService->ChildrenNumber++;\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+ERROR:\r
+\r
+ if (EFI_ERROR (Status)) {\r
+\r
+ gBS->CloseProtocol (\r
+ ArpService->MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ gArpDriverBinding.DriverBindingHandle,\r
+ Instance->Handle\r
+ );\r
+\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Instance->Handle,\r
+ &gEfiArpProtocolGuid,\r
+ &Instance->ArpProto,\r
+ NULL\r
+ );\r
+\r
+ //\r
+ // Free the allocated memory.\r
+ //\r
+ NetFreePool (Instance);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Destroys a child handle with a set of I/O services.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ChildHandle Handle of the child to destroy.\r
+\r
+ @retval EFI_SUCCES The I/O services were removed from the child\r
+ handle.\r
+ @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
+ that are being removed.\r
+ @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
+ @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
+ its I/O services are being used.\r
+ @retval other The child handle was not destroyed.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpServiceBindingDestroyChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ChildHandle\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ ARP_INSTANCE_DATA *Instance;\r
+ EFI_ARP_PROTOCOL *Arp;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ ArpService = ARP_SERVICE_DATA_FROM_THIS (This);\r
+\r
+ //\r
+ // Get the arp protocol.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandle,\r
+ &gEfiArpProtocolGuid,\r
+ (VOID **)&Arp,\r
+ ArpService->ImageHandle,\r
+ ChildHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (Arp);\r
+\r
+ if (Instance->Destroyed) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Use the Destroyed as a flag to avoid re-entrance.\r
+ //\r
+ Instance->Destroyed = TRUE;\r
+\r
+ //\r
+ // Close the Managed Network protocol.\r
+ //\r
+ gBS->CloseProtocol (\r
+ ArpService->MnpChildHandle,\r
+ &gEfiManagedNetworkProtocolGuid,\r
+ gArpDriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+\r
+ //\r
+ // Uninstall the ARP protocol.\r
+ //\r
+ Status = gBS->UninstallMultipleProtocolInterfaces (\r
+ ChildHandle,\r
+ &gEfiArpProtocolGuid,\r
+ &Instance->ArpProto,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ARP_DEBUG_ERROR (("ArpSBDestroyChild: Failed to uninstall the arp protocol, %r.\n",\r
+ Status));\r
+\r
+ Instance->Destroyed = FALSE;\r
+ return Status;\r
+ }\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ Instance->Destroyed = FALSE;\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ if (Instance->Configured) {\r
+ //\r
+ // Delete the related cache entry.\r
+ //\r
+ ArpDeleteCacheEntry (Instance, FALSE, NULL, TRUE);\r
+\r
+ //\r
+ // Reset the instance configuration.\r
+ //\r
+ ArpConfigureInstance (Instance, NULL);\r
+ }\r
+\r
+ //\r
+ // Remove this instance from the ChildrenList.\r
+ //\r
+ NetListRemoveEntry (&Instance->List);\r
+ ArpService->ChildrenNumber--;\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+ NetFreePool (Instance);\r
+\r
+ return Status;\r
+}\r
+\r
+//@MT: EFI_DRIVER_ENTRY_POINT (ArpDriverEntryPoint)\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ The entry point for Arp driver which installs the driver binding and component name\r
+ protocol on its ImageHandle.\r
+\r
+Arguments:\r
+\r
+ ImageHandle - The image handle of the driver.\r
+ SystemTable - The system table.\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - if the driver binding and component name protocols are successfully\r
+ installed, otherwise if failed.\r
+\r
+--*/\r
+{\r
+ return NetLibInstallAllDriverProtocols (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gArpDriverBinding,\r
+ ImageHandle,\r
+ &gArpComponentName,\r
+ NULL,\r
+ NULL\r
+ );\r
+}\r
+\r
--- /dev/null
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. 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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpDriver.c
+
+Abstract:
+
+
+**/
+
+#ifndef _ARP_DRIVER_H_
+#define _ARP_DRIVER_H_
+
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Arp.h>\r
+#include <Protocol/ManagedNetwork.h>
+#include <Protocol/ServiceBinding.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>
+
+#include "ArpDebug.h"
+
+//
+// Global variables
+//
+extern EFI_DRIVER_BINDING_PROTOCOL gArpDriverBinding;
+extern EFI_COMPONENT_NAME_PROTOCOL gArpComponentName;
+
+EFI_STATUS
+EFIAPI
+ArpDriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpDriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpDriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+ArpServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+EFI_STATUS
+EFIAPI
+ArpServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+
+#endif
+
--- /dev/null
+#/** @file\r
+# Component description file for ARP module\r
+#\r
+# Copyright (c) 2006, Intel Corporation\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = ArpDxe\r
+ FILE_GUID = 529D3F93-E8E9-4e73-B1E1-BDF6A9D50113\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = ArpDriverEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ ArpMain.c\r
+ ArpDriver.h\r
+ ComponentName.c\r
+ ArpImpl.h\r
+ ArpImpl.c\r
+ ArpDebug.h\r
+ ArpDriver.c\r
+\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+ NetLib\r
+\r
+\r
+[Protocols]\r
+ gEfiManagedNetworkServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiArpServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiManagedNetworkProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiArpProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+\r
--- /dev/null
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>Arp</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>529D3F93-E8E9-4e73-B1E1-BDF6A9D50113</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component name for module Arp</Abstract>\r
+ <Description>FIX ME!</Description>\r
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+ <License>All rights reserved. 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
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>Arp</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>ArpDriver.c</Filename>\r
+ <Filename>ArpDebug.h</Filename>\r
+ <Filename>ArpImpl.c</Filename>\r
+ <Filename>ArpImpl.h</Filename>\r
+ <Filename>ComponentName.c</Filename>\r
+ <Filename>ArpDriver.h</Filename>\r
+ <Filename>ArpMain.c</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiArpProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiManagedNetworkProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiArpServiceBindingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiManagedNetworkServiceBindingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>ArpDriverEntryPoint</ModuleEntryPoint>\r
+ </Extern>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ ArpImpl.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+\r
+#include "ArpImpl.h"\r
+#include "ArpDebug.h"\r
+\r
+EFI_ARP_PROTOCOL mEfiArpProtocolTemplate = {\r
+ ArpConfigure,\r
+ ArpAdd,\r
+ ArpFind,\r
+ ArpDelete,\r
+ ArpFlush,\r
+ ArpRequest,\r
+ ArpCancel\r
+};\r
+\r
+\r
+/**\r
+ Initialize the instance context data.\r
+\r
+ @param ArpService Pointer to the arp service context data this\r
+ instance belongs to.\r
+ @param Instance Pointer to the instance context data.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+ArpInitInstance (\r
+ IN ARP_SERVICE_DATA *ArpService,\r
+ IN ARP_INSTANCE_DATA *Instance\r
+ )\r
+{\r
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
+\r
+ Instance->Signature = ARP_INSTANCE_DATA_SIGNATURE;\r
+ Instance->ArpService = ArpService;\r
+\r
+ CopyMem (&Instance->ArpProto, &mEfiArpProtocolTemplate, sizeof (ARP_SERVICE_DATA));\r
+\r
+ Instance->Configured = FALSE;\r
+ Instance->Destroyed = FALSE;\r
+\r
+ NetListInit (&Instance->List);\r
+}\r
+\r
+\r
+/**\r
+ Process the Arp packets received from Mnp, the procedure conforms to RFC826.\r
+\r
+ @param Event The Event this notify function registered to.\r
+ @param Context Pointer to the context data registerd to the\r
+ Event.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ArpOnFrameRcvd (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN *RxToken;\r
+ EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData;\r
+ ARP_HEAD *Head;\r
+ ARP_ADDRESS ArpAddress;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ NET_LIST_ENTRY *Entry;\r
+ ARP_INSTANCE_DATA *Instance;\r
+ EFI_ARP_CONFIG_DATA *ConfigData;\r
+ NET_ARP_ADDRESS SenderAddress[2];\r
+ BOOLEAN ProtoMatched;\r
+ BOOLEAN IsTarget;\r
+ BOOLEAN MergeFlag;\r
+\r
+ ArpService = (ARP_SERVICE_DATA *)Context;\r
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
+\r
+ RxToken = &ArpService->RxToken;\r
+\r
+ if (RxToken->Status == EFI_ABORTED) {\r
+ //\r
+ // The Token is aborted, possibly by arp itself, just return and the receiving\r
+ // process is stopped.\r
+ //\r
+ return;\r
+ }\r
+\r
+ if (EFI_ERROR (RxToken->Status)) {\r
+ //\r
+ // Restart the receiving if any other error Status occurs.\r
+ //\r
+ goto RESTART_RECEIVE;\r
+ }\r
+\r
+ //\r
+ // Status is EFI_SUCCESS, process the received frame.\r
+ //\r
+ RxData = RxToken->Packet.RxData;\r
+ Head = (ARP_HEAD *) RxData->PacketData;\r
+\r
+ //\r
+ // Convert the byte order of the multi-byte fields.\r
+ //\r
+ Head->HwType = NTOHS (Head->HwType);\r
+ Head->ProtoType = NTOHS (Head->ProtoType);\r
+ Head->OpCode = NTOHS (Head->OpCode);\r
+\r
+ if ((Head->HwType != ArpService->SnpMode.IfType) ||\r
+ (Head->HwAddrLen != ArpService->SnpMode.HwAddressSize) ||\r
+ (RxData->ProtocolType != ARP_ETHER_PROTO_TYPE)) {\r
+ //\r
+ // The hardware type or the hardware address length doesn't match.\r
+ // There is a sanity check for the protocol type too.\r
+ //\r
+ goto RECYCLE_RXDATA;\r
+ }\r
+\r
+ //\r
+ // Set the pointers to the addresses contained in the arp packet.\r
+ //\r
+ ArpAddress.SenderHwAddr = (UINT8 *)(Head + 1);\r
+ ArpAddress.SenderProtoAddr = ArpAddress.SenderHwAddr + Head->HwAddrLen;\r
+ ArpAddress.TargetHwAddr = ArpAddress.SenderProtoAddr + Head->ProtoAddrLen;\r
+ ArpAddress.TargetProtoAddr = ArpAddress.TargetHwAddr + Head->HwAddrLen;\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ ARP_DEBUG_ERROR (("ArpOnFrameRcvd: Faild to acquire the CacheTableLock.\n"));\r
+ goto RECYCLE_RXDATA;\r
+ }\r
+\r
+ SenderAddress[Hardware].Type = Head->HwType;\r
+ SenderAddress[Hardware].Length = Head->HwAddrLen;\r
+ SenderAddress[Hardware].AddressPtr = ArpAddress.SenderHwAddr;\r
+\r
+ SenderAddress[Protocol].Type = Head->ProtoType;\r
+ SenderAddress[Protocol].Length = Head->ProtoAddrLen;\r
+ SenderAddress[Protocol].AddressPtr = ArpAddress.SenderProtoAddr;\r
+\r
+ //\r
+ // First, check the denied cache table.\r
+ //\r
+ CacheEntry = ArpFindDeniedCacheEntry (\r
+ ArpService,\r
+ &SenderAddress[Protocol],\r
+ &SenderAddress[Hardware]\r
+ );\r
+ if (CacheEntry != NULL) {\r
+ //\r
+ // This address (either hardware or protocol address, or both) is configured to\r
+ // be a deny entry, silently skip the normal process.\r
+ //\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ ProtoMatched = FALSE;\r
+ IsTarget = FALSE;\r
+ Instance = NULL;\r
+ NET_LIST_FOR_EACH (Entry, &ArpService->ChildrenList) {\r
+ //\r
+ // Iterate all the children.\r
+ //\r
+ Instance = NET_LIST_USER_STRUCT (Entry, ARP_INSTANCE_DATA, List);\r
+ NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);\r
+ ConfigData = &Instance->ConfigData;\r
+\r
+ if ((Instance->Configured) &&\r
+ (Head->ProtoType == ConfigData->SwAddressType) &&\r
+ (Head->ProtoAddrLen == ConfigData->SwAddressLength)) {\r
+ //\r
+ // The protocol type is matched for the received arp packet.\r
+ //\r
+ ProtoMatched = TRUE;\r
+ if (0 == NetCompareMem (\r
+ (VOID *)ArpAddress.TargetProtoAddr,\r
+ ConfigData->StationAddress,\r
+ ConfigData->SwAddressLength\r
+ )) {\r
+ //\r
+ // The arp driver has the target address required by the received arp packet.\r
+ //\r
+ IsTarget = TRUE;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (!ProtoMatched) {\r
+ //\r
+ // Protocol type unmatchable, skip.\r
+ //\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check whether the sender's address information is already in the cache.\r
+ //\r
+ MergeFlag = FALSE;\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->ResolvedCacheTable,\r
+ NULL,\r
+ ByProtoAddress,\r
+ &SenderAddress[Protocol],\r
+ NULL\r
+ );\r
+ if (CacheEntry != NULL) {\r
+ //\r
+ // Update the entry with the new information.\r
+ //\r
+ ArpFillAddressInCacheEntry (CacheEntry, &SenderAddress[Hardware], NULL);\r
+ CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;\r
+ MergeFlag = TRUE;\r
+ }\r
+\r
+ if (!IsTarget) {\r
+ //\r
+ // This arp packet isn't targeted to us, skip now.\r
+ //\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ if (!MergeFlag) {\r
+ //\r
+ // Add the triplet <protocol type, sender protocol address, sender hardware address>\r
+ // to the translation table.\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->PendingRequestTable,\r
+ NULL,\r
+ ByProtoAddress,\r
+ &SenderAddress[Protocol],\r
+ NULL\r
+ );\r
+ if (CacheEntry == NULL) {\r
+ //\r
+ // Allocate a new CacheEntry.\r
+ //\r
+ CacheEntry = ArpAllocCacheEntry (NULL);\r
+ if (CacheEntry == NULL) {\r
+ goto UNLOCK_EXIT;\r
+ }\r
+ }\r
+\r
+ NetListRemoveEntry (&CacheEntry->List);\r
+\r
+ //\r
+ // Fill the addresses into the CacheEntry.\r
+ //\r
+ ArpFillAddressInCacheEntry (\r
+ CacheEntry,\r
+ &SenderAddress[Hardware],\r
+ &SenderAddress[Protocol]\r
+ );\r
+\r
+ //\r
+ // Inform the user.\r
+ //\r
+ ArpAddressResolved (CacheEntry, NULL, NULL);\r
+\r
+ //\r
+ // Add this entry into the ResolvedCacheTable\r
+ //\r
+ NetListInsertHead (&ArpService->ResolvedCacheTable, &CacheEntry->List);\r
+ }\r
+\r
+ if (Head->OpCode == ARP_OPCODE_REQUEST) {\r
+ //\r
+ // Send back the ARP Reply. If we reach here, Instance is not NULL and CacheEntry\r
+ // is not NULL.\r
+ //\r
+ ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REPLY);\r
+ }\r
+\r
+UNLOCK_EXIT:\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+RECYCLE_RXDATA:\r
+\r
+ //\r
+ // Signal Mnp to recycle the RxData.\r
+ //\r
+ gBS->SignalEvent (RxData->RecycleEvent);\r
+\r
+RESTART_RECEIVE:\r
+\r
+ //\r
+ // Continue to receive packets from Mnp.\r
+ //\r
+ Status = ArpService->Mnp->Receive (ArpService->Mnp, RxToken);\r
+\r
+ DEBUG_CODE (\r
+ if (EFI_ERROR (Status)) {\r
+ ARP_DEBUG_ERROR (("ArpOnFrameRcvd: ArpService->Mnp->Receive "\r
+ "failed, %r\n.", Status));\r
+ }\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Process the already sent arp packets.\r
+\r
+ @param Event The Event this notify function registered to.\r
+ @param Context Pointer to the context data registerd to the\r
+ Event.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ArpOnFrameSent (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;\r
+ EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
+\r
+ ASSERT (Context != NULL);\r
+\r
+ TxToken = (EFI_MANAGED_NETWORK_COMPLETION_TOKEN *)Context;\r
+ TxData = TxToken->Packet.TxData;\r
+\r
+ DEBUG_CODE (\r
+ if (EFI_ERROR (TxToken->Status)) {\r
+ ARP_DEBUG_ERROR (("ArpOnFrameSent: TxToken->Status, %r.\n", TxToken->Status));\r
+ }\r
+ );\r
+\r
+ //\r
+ // Free the allocated memory and close the event.\r
+ //\r
+ NetFreePool (TxData->FragmentTable[0].FragmentBuffer);\r
+ NetFreePool (TxData);\r
+ gBS->CloseEvent (TxToken->Event);\r
+ NetFreePool (TxToken);\r
+}\r
+\r
+\r
+/**\r
+ Process the arp cache olding and drive the retrying arp requests.\r
+\r
+ @param Event The Event this notify function registered to.\r
+ @param Context Pointer to the context data registerd to the\r
+ Event.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+ArpTimerHandler (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ ARP_SERVICE_DATA *ArpService;\r
+ NET_LIST_ENTRY *Entry;\r
+ NET_LIST_ENTRY *NextEntry;\r
+ NET_LIST_ENTRY *ContextEntry;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ USER_REQUEST_CONTEXT *RequestContext;\r
+\r
+ ASSERT (Context != NULL);\r
+ ArpService = (ARP_SERVICE_DATA *)Context;\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ return;\r
+ }\r
+\r
+ //\r
+ // Iterate all the pending requests to see whether a retry is needed to send out\r
+ // or the request finally fails because the retry time reaches the limitation.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {\r
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
+\r
+ if (CacheEntry->NextRetryTime <= ARP_PERIODIC_TIMER_INTERVAL) {\r
+ //\r
+ // Timeout, if we can retry more, send out the request again, otherwise abort\r
+ // this request.\r
+ //\r
+ if (CacheEntry->RetryCount == 0) {\r
+ //\r
+ // Abort this request.\r
+ //\r
+ ArpAddressResolved (CacheEntry, NULL, NULL);\r
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));\r
+\r
+ NetListRemoveEntry (&CacheEntry->List);\r
+ NetFreePool (CacheEntry);\r
+ } else {\r
+ //\r
+ // resend the ARP request.\r
+ //\r
+ ASSERT (!NetListIsEmpty(&CacheEntry->UserRequestList));\r
+\r
+ ContextEntry = CacheEntry->UserRequestList.ForwardLink;\r
+ RequestContext = NET_LIST_USER_STRUCT (ContextEntry, USER_REQUEST_CONTEXT, List);\r
+\r
+ ArpSendFrame (RequestContext->Instance, CacheEntry, ARP_OPCODE_REQUEST);\r
+\r
+ CacheEntry->RetryCount--;\r
+ CacheEntry->NextRetryTime = RequestContext->Instance->ConfigData.RetryTimeOut;\r
+ }\r
+ } else {\r
+ //\r
+ // Update the NextRetryTime.\r
+ //\r
+ CacheEntry->NextRetryTime -= ARP_PERIODIC_TIMER_INTERVAL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check the timeouts for the DeniedCacheTable.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->DeniedCacheTable) {\r
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));\r
+\r
+ if (CacheEntry->DefaultDecayTime == 0) {\r
+ //\r
+ // It's a static entry, skip it.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {\r
+ //\r
+ // Time out, remove it.\r
+ //\r
+ NetListRemoveEntry (&CacheEntry->List);\r
+ NetFreePool (CacheEntry);\r
+ } else {\r
+ //\r
+ // Update the DecayTime.\r
+ //\r
+ CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Check the timeouts for the ResolvedCacheTable.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->ResolvedCacheTable) {\r
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));\r
+\r
+ if (CacheEntry->DefaultDecayTime == 0) {\r
+ //\r
+ // It's a static entry, skip it.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ if (CacheEntry->DecayTime <= ARP_PERIODIC_TIMER_INTERVAL) {\r
+ //\r
+ // Time out, remove it.\r
+ //\r
+ NetListRemoveEntry (&CacheEntry->List);\r
+ NetFreePool (CacheEntry);\r
+ } else {\r
+ //\r
+ // Update the DecayTime.\r
+ //\r
+ CacheEntry->DecayTime -= ARP_PERIODIC_TIMER_INTERVAL;\r
+ }\r
+ }\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+}\r
+\r
+\r
+/**\r
+ Match the two NET_ARP_ADDRESSes.\r
+\r
+ @param AddressOne Pointer to the first address to match.\r
+ @param AddressTwo Pointer to the second address to match.\r
+\r
+ @return The two addresses match or not.\r
+\r
+**/\r
+STATIC\r
+BOOLEAN\r
+ArpMatchAddress (\r
+ IN NET_ARP_ADDRESS *AddressOne,\r
+ IN NET_ARP_ADDRESS *AddressTwo\r
+ )\r
+{\r
+ if ((AddressOne->Type != AddressTwo->Type) ||\r
+ (AddressOne->Length != AddressTwo->Length)) {\r
+ //\r
+ // Either Type or Length doesn't match.\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ if ((AddressOne->AddressPtr != NULL) &&\r
+ (NetCompareMem (\r
+ AddressOne->AddressPtr,\r
+ AddressTwo->AddressPtr,\r
+ AddressOne->Length\r
+ ) != 0)) {\r
+ //\r
+ // The address is not the same.\r
+ //\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+\r
+/**\r
+ Find the CacheEntry which matches the requirements in the specified CacheTable.\r
+\r
+ @param CacheTable Pointer to the arp cache table.\r
+ @param StartEntry Pointer to the start entry this search begins with\r
+ in the cache table.\r
+ @param FindOpType The search type.\r
+ @param ProtocolAddress Pointer to the protocol address to match.\r
+ @param HardwareAddress Pointer to the hardware address to match.\r
+\r
+ @return Pointer to the matched arp cache entry, if NULL, no match is found.\r
+\r
+**/\r
+ARP_CACHE_ENTRY *\r
+ArpFindNextCacheEntryInTable (\r
+ IN NET_LIST_ENTRY *CacheTable,\r
+ IN NET_LIST_ENTRY *StartEntry,\r
+ IN FIND_OPTYPE FindOpType,\r
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,\r
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL\r
+ )\r
+{\r
+ NET_LIST_ENTRY *Entry;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+\r
+ if (StartEntry == NULL) {\r
+ //\r
+ // Start from the beginning of the table if no StartEntry is specified.\r
+ //\r
+ StartEntry = CacheTable;\r
+ }\r
+\r
+ for (Entry = StartEntry->ForwardLink; Entry != CacheTable; Entry = Entry->ForwardLink) {\r
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
+\r
+ if (FindOpType & MATCH_SW_ADDRESS) {\r
+ //\r
+ // Find by the software address.\r
+ //\r
+ if (!ArpMatchAddress (ProtocolAddress, &CacheEntry->Addresses[Protocol])) {\r
+ //\r
+ // The ProtocolAddress doesn't match, continue to the next cache entry.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ if (FindOpType & MATCH_HW_ADDRESS) {\r
+ //\r
+ // Find by the hardware address.\r
+ //\r
+ if (!ArpMatchAddress (HardwareAddress, &CacheEntry->Addresses[Hardware])) {\r
+ //\r
+ // The HardwareAddress doesn't match, continue to the next cache entry.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
+ //\r
+ // The CacheEntry meets the requirements now, return this entry.\r
+ //\r
+ return CacheEntry;\r
+ }\r
+\r
+ //\r
+ // No matching.\r
+ //\r
+ return NULL;\r
+}\r
+\r
+\r
+/**\r
+ Find the CacheEntry, using ProtocolAddress or HardwareAddress or both, as the keyword,\r
+ in the DeniedCacheTable.\r
+\r
+ @param ArpService Pointer to the arp service context data.\r
+ @param ProtocolAddress Pointer to the protocol address.\r
+ @param HardwareAddress Pointer to the hardware address.\r
+\r
+ @return Pointer to the matched cache entry, if NULL no match is found.\r
+\r
+**/\r
+ARP_CACHE_ENTRY *\r
+ArpFindDeniedCacheEntry (\r
+ IN ARP_SERVICE_DATA *ArpService,\r
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,\r
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL\r
+ )\r
+{\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+\r
+ ASSERT ((ProtocolAddress != NULL) || (HardwareAddress != NULL));\r
+ NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE);\r
+\r
+ CacheEntry = NULL;\r
+\r
+ if ((ProtocolAddress != NULL) && (ProtocolAddress->AddressPtr != NULL)) {\r
+ //\r
+ // Find the cache entry in the DeniedCacheTable by the protocol address.\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->DeniedCacheTable,\r
+ NULL,\r
+ ByProtoAddress,\r
+ ProtocolAddress,\r
+ NULL\r
+ );\r
+ if (CacheEntry != NULL) {\r
+ //\r
+ // There is a match.\r
+ //\r
+ return CacheEntry;\r
+ }\r
+ }\r
+\r
+ if ((HardwareAddress != NULL) && (HardwareAddress->AddressPtr != NULL)) {\r
+ //\r
+ // Find the cache entry in the DeniedCacheTable by the hardware address.\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->DeniedCacheTable,\r
+ NULL,\r
+ ByHwAddress,\r
+ NULL,\r
+ HardwareAddress\r
+ );\r
+ }\r
+\r
+ return CacheEntry;\r
+}\r
+\r
+\r
+/**\r
+ Allocate a cache entry and initialize it.\r
+\r
+ @param Instance Pointer to the instance context data.\r
+\r
+ @return Pointer to the new created cache entry.\r
+\r
+**/\r
+ARP_CACHE_ENTRY *\r
+ArpAllocCacheEntry (\r
+ IN ARP_INSTANCE_DATA *Instance\r
+ )\r
+{\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ NET_ARP_ADDRESS *Address;\r
+ UINT16 Index;\r
+\r
+ //\r
+ // Allocate memory for the cache entry.\r
+ //\r
+ CacheEntry = NetAllocatePool (sizeof (ARP_CACHE_ENTRY));\r
+ if (CacheEntry == NULL) {\r
+ return NULL;\r
+ }\r
+\r
+ //\r
+ // Init the lists.\r
+ //\r
+ NetListInit (&CacheEntry->List);\r
+ NetListInit (&CacheEntry->UserRequestList);\r
+\r
+ for (Index = 0; Index < 2; Index++) {\r
+ //\r
+ // Init the address pointers to point to the concrete buffer.\r
+ //\r
+ Address = &CacheEntry->Addresses[Index];\r
+ Address->AddressPtr = Address->Buffer.ProtoAddress;\r
+ }\r
+\r
+ //\r
+ // Zero the hardware address first.\r
+ //\r
+ NetZeroMem (CacheEntry->Addresses[Hardware].AddressPtr, ARP_MAX_HARDWARE_ADDRESS_LEN);\r
+\r
+ if (Instance != NULL) {\r
+ //\r
+ // Inherit the parameters from the instance configuration.\r
+ //\r
+ CacheEntry->RetryCount = Instance->ConfigData.RetryCount;\r
+ CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;\r
+ CacheEntry->DefaultDecayTime = Instance->ConfigData.EntryTimeOut;\r
+ CacheEntry->DecayTime = Instance->ConfigData.EntryTimeOut;\r
+ } else {\r
+ //\r
+ // Use the default parameters if this cache entry isn't allocate in a\r
+ // instance's scope.\r
+ //\r
+ CacheEntry->RetryCount = ARP_DEFAULT_RETRY_COUNT;\r
+ CacheEntry->NextRetryTime = ARP_DEFAULT_RETRY_INTERVAL;\r
+ CacheEntry->DefaultDecayTime = ARP_DEFAULT_TIMEOUT_VALUE;\r
+ CacheEntry->DecayTime = ARP_DEFAULT_TIMEOUT_VALUE;\r
+ }\r
+\r
+ return CacheEntry;\r
+}\r
+\r
+\r
+/**\r
+ Turn the CacheEntry into the resolved status.\r
+\r
+ @param CacheEntry Pointer to the resolved cache entry.\r
+ @param Instance Pointer to the instance context data.\r
+ @param UserEvent Pointer to the UserEvent to notify.\r
+\r
+ @return The count of notifications sent to the instance.\r
+\r
+**/\r
+UINTN\r
+ArpAddressResolved (\r
+ IN ARP_CACHE_ENTRY *CacheEntry,\r
+ IN ARP_INSTANCE_DATA *Instance OPTIONAL,\r
+ IN EFI_EVENT UserEvent OPTIONAL\r
+ )\r
+{\r
+ NET_LIST_ENTRY *Entry;\r
+ NET_LIST_ENTRY *NextEntry;\r
+ USER_REQUEST_CONTEXT *Context;\r
+ UINTN Count;\r
+\r
+ Count = 0;\r
+\r
+ //\r
+ // Iterate all the linked user requests to notify them.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &CacheEntry->UserRequestList) {\r
+ Context = NET_LIST_USER_STRUCT (Entry, USER_REQUEST_CONTEXT, List);\r
+\r
+ if (((Instance == NULL) || (Context->Instance == Instance)) &&\r
+ ((UserEvent == NULL) || (Context->UserRequestEvent == UserEvent))) {\r
+ //\r
+ // Copy the address to the user-provided buffer and notify the user.\r
+ //\r
+ NetCopyMem (\r
+ Context->UserHwAddrBuffer,\r
+ CacheEntry->Addresses[Hardware].AddressPtr,\r
+ CacheEntry->Addresses[Hardware].Length\r
+ );\r
+ gBS->SignalEvent (Context->UserRequestEvent);\r
+\r
+ //\r
+ // Remove this user request and free the context data.\r
+ //\r
+ NetListRemoveEntry (&Context->List);\r
+ NetFreePool (Context);\r
+\r
+ Count++;\r
+ }\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+\r
+/**\r
+ Fill the addresses in the CacheEntry using the information passed in by\r
+ HwAddr and SwAddr.\r
+\r
+ @param CacheEntry Pointer to the cache entry.\r
+ @param HwAddr Pointer to the software address.\r
+ @param SwAddr Pointer to the hardware address.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+ArpFillAddressInCacheEntry (\r
+ IN ARP_CACHE_ENTRY *CacheEntry,\r
+ IN NET_ARP_ADDRESS *HwAddr OPTIONAL,\r
+ IN NET_ARP_ADDRESS *SwAddr OPTIONAL\r
+ )\r
+{\r
+ NET_ARP_ADDRESS *Address[2];\r
+ NET_ARP_ADDRESS *CacheAddress;\r
+ UINT32 Index;\r
+\r
+ Address[Hardware] = HwAddr;\r
+ Address[Protocol] = SwAddr;\r
+\r
+ for (Index = 0; Index < 2; Index++) {\r
+ if (Address[Index] != NULL) {\r
+ //\r
+ // Fill the address if the passed in pointer is not NULL.\r
+ //\r
+ CacheAddress = &CacheEntry->Addresses[Index];\r
+\r
+ CacheAddress->Type = Address[Index]->Type;\r
+ CacheAddress->Length = Address[Index]->Length;\r
+\r
+ if (Address[Index]->AddressPtr != NULL) {\r
+ //\r
+ // Copy it if the AddressPtr points to some buffer.\r
+ //\r
+ NetCopyMem (\r
+ CacheAddress->AddressPtr,\r
+ Address[Index]->AddressPtr,\r
+ CacheAddress->Length\r
+ );\r
+ } else {\r
+ //\r
+ // Zero the corresponding address buffer in the CacheEntry.\r
+ //\r
+ NetZeroMem (CacheAddress->AddressPtr, CacheAddress->Length);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Configure the instance using the ConfigData. ConfigData is already validated.\r
+\r
+ @param Instance Pointer to the instance context data to be\r
+ configured.\r
+ @param ConfigData Pointer to the configuration data used to\r
+ configure the instance.\r
+\r
+ @retval EFI_SUCCESS The instance is configured with the ConfigData.\r
+ @retval EFI_ACCESS_DENIED The instance is already configured and the\r
+ ConfigData tries to reset some unchangeable\r
+ fields.\r
+ @retval EFI_INVALID_PARAMETER The ConfigData provides a non-unicast IPv4 address\r
+ when the SwAddressType is IPv4.\r
+ @retval EFI_OUT_OF_RESOURCES The instance fails to configure due to memory\r
+ limitation.\r
+\r
+**/\r
+EFI_STATUS\r
+ArpConfigureInstance (\r
+ IN ARP_INSTANCE_DATA *Instance,\r
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL\r
+ )\r
+{\r
+ EFI_ARP_CONFIG_DATA *OldConfigData;\r
+ IP4_ADDR Ip;\r
+\r
+ OldConfigData = &Instance->ConfigData;\r
+\r
+ if (ConfigData != NULL) {\r
+\r
+ if (Instance->Configured) {\r
+ //\r
+ // The instance is configured, check the unchangeable fields.\r
+ //\r
+ if ((OldConfigData->SwAddressType != ConfigData->SwAddressType) ||\r
+ (OldConfigData->SwAddressLength != ConfigData->SwAddressLength) ||\r
+ (NetCompareMem (\r
+ OldConfigData->StationAddress,\r
+ ConfigData->StationAddress,\r
+ OldConfigData->SwAddressLength\r
+ ) != 0)) {\r
+ //\r
+ // Deny the unallowed changes.\r
+ //\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+ } else {\r
+ //\r
+ // The instance is not configured.\r
+ //\r
+\r
+ if (ConfigData->SwAddressType == IPv4_ETHER_PROTO_TYPE) {\r
+ NetCopyMem (&Ip, ConfigData->StationAddress, sizeof (IP4_ADDR));\r
+\r
+ if (!Ip4IsUnicast (NTOHL (Ip), 0)) {\r
+ //\r
+ // The station address is not a valid IPv4 unicast address.\r
+ //\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Save the configuration.\r
+ //\r
+ CopyMem (OldConfigData, ConfigData, sizeof (EFI_ARP_CONFIG_DATA));\r
+\r
+ OldConfigData->StationAddress = NetAllocatePool (OldConfigData->SwAddressLength);\r
+ if (OldConfigData->StationAddress == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpConfigInstance: NetAllocatePool for the StationAddress "\r
+ "failed.\n"));\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ //\r
+ // Save the StationAddress.\r
+ //\r
+ NetCopyMem (\r
+ OldConfigData->StationAddress,\r
+ ConfigData->StationAddress,\r
+ OldConfigData->SwAddressLength\r
+ );\r
+\r
+ //\r
+ // Set the state to configured.\r
+ //\r
+ Instance->Configured = TRUE;\r
+ }\r
+\r
+ //\r
+ // Use the implementation specific values if the following field is zero.\r
+ //\r
+ OldConfigData->EntryTimeOut = (ConfigData->EntryTimeOut == 0) ?\r
+ ARP_DEFAULT_TIMEOUT_VALUE : ConfigData->EntryTimeOut;\r
+\r
+ OldConfigData->RetryCount = (ConfigData->RetryCount == 0) ?\r
+ ARP_DEFAULT_RETRY_COUNT : ConfigData->RetryCount;\r
+\r
+ OldConfigData->RetryTimeOut = (ConfigData->RetryTimeOut == 0) ?\r
+ ARP_DEFAULT_RETRY_INTERVAL : ConfigData->RetryTimeOut;\r
+ } else {\r
+ //\r
+ // Reset the configuration.\r
+ //\r
+\r
+ if (Instance->Configured) {\r
+ //\r
+ // Cancel the arp requests issued by this instance.\r
+ //\r
+ ArpCancelRequest (Instance, NULL, NULL);\r
+\r
+ //\r
+ // Free the buffer previously allocated to hold the station address.\r
+ //\r
+ NetFreePool (OldConfigData->StationAddress);\r
+ }\r
+\r
+ Instance->Configured = FALSE;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Send out an arp frame using the CachEntry and the ArpOpCode.\r
+\r
+ @param Instance Pointer to the instance context data.\r
+ @param CacheEntry Pointer to the configuration data used to\r
+ configure the instance.\r
+ @param ArpOpCode The opcode used to send out this Arp frame, either\r
+ request or reply.\r
+\r
+ @return None.\r
+\r
+**/\r
+VOID\r
+ArpSendFrame (\r
+ IN ARP_INSTANCE_DATA *Instance,\r
+ IN ARP_CACHE_ENTRY *CacheEntry,\r
+ IN UINT16 ArpOpCode\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN *TxToken;\r
+ EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData;\r
+ UINT32 TotalLength;\r
+ UINT8 *Packet;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
+ EFI_ARP_CONFIG_DATA *ConfigData;\r
+ UINT8 *TmpPtr;\r
+ ARP_HEAD *ArpHead;\r
+\r
+ ASSERT ((Instance != NULL) && (CacheEntry != NULL));\r
+\r
+ //\r
+ // Allocate memory for the TxToken.\r
+ //\r
+ TxToken = NetAllocatePool (sizeof(EFI_MANAGED_NETWORK_COMPLETION_TOKEN));\r
+ if (TxToken == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for TxToken failed.\n"));\r
+ return;\r
+ }\r
+\r
+ TxToken->Event = NULL;\r
+ TxData = NULL;\r
+ Packet = NULL;\r
+\r
+ //\r
+ // Create the event for this TxToken.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ NET_TPL_EVENT,\r
+ ArpOnFrameSent,\r
+ (VOID *)TxToken,\r
+ &TxToken->Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ ARP_DEBUG_ERROR (("ArpSendFrame: CreateEvent failed for TxToken->Event.\n"));\r
+ goto CLEAN_EXIT;\r
+ }\r
+\r
+ //\r
+ // Allocate memory for the TxData used in the TxToken.\r
+ //\r
+ TxData = NetAllocatePool (sizeof(EFI_MANAGED_NETWORK_TRANSMIT_DATA));\r
+ if (TxData == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for TxData failed.\n"));\r
+ goto CLEAN_EXIT;\r
+ }\r
+\r
+ ArpService = Instance->ArpService;\r
+ SnpMode = &ArpService->SnpMode;\r
+ ConfigData = &Instance->ConfigData;\r
+\r
+ //\r
+ // Calculate the buffer length for this arp frame.\r
+ //\r
+ TotalLength = SnpMode->MediaHeaderSize + sizeof (ARP_HEAD) +\r
+ 2 * (ConfigData->SwAddressLength + SnpMode->HwAddressSize);\r
+\r
+ //\r
+ // Allocate buffer for the arp frame.\r
+ //\r
+ Packet = NetAllocatePool (TotalLength);\r
+ if (Packet == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpSendFrame: Allocate memory for Packet failed.\n"));\r
+ }\r
+\r
+ TmpPtr = Packet;\r
+\r
+ //\r
+ // The destination MAC address.\r
+ //\r
+ if (ArpOpCode == ARP_OPCODE_REQUEST) {\r
+ NetCopyMem (TmpPtr, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);\r
+ } else {\r
+ NetCopyMem (\r
+ TmpPtr,\r
+ CacheEntry->Addresses[Hardware].AddressPtr,\r
+ SnpMode->HwAddressSize\r
+ );\r
+ }\r
+ TmpPtr += SnpMode->HwAddressSize;\r
+\r
+ //\r
+ // The source MAC address.\r
+ //\r
+ NetCopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);\r
+ TmpPtr += SnpMode->HwAddressSize;\r
+\r
+ //\r
+ // The ethernet protocol type.\r
+ //\r
+ *(UINT16 *)TmpPtr = HTONS (ARP_ETHER_PROTO_TYPE);\r
+ TmpPtr += 2;\r
+\r
+ //\r
+ // The ARP Head.\r
+ //\r
+ ArpHead = (ARP_HEAD *) TmpPtr;\r
+ ArpHead->HwType = HTONS ((UINT16)SnpMode->IfType);\r
+ ArpHead->ProtoType = HTONS (ConfigData->SwAddressType);\r
+ ArpHead->HwAddrLen = (UINT8)SnpMode->HwAddressSize;\r
+ ArpHead->ProtoAddrLen = ConfigData->SwAddressLength;\r
+ ArpHead->OpCode = HTONS (ArpOpCode);\r
+ TmpPtr += sizeof (ARP_HEAD);\r
+\r
+ //\r
+ // The sender hardware address.\r
+ //\r
+ NetCopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize);\r
+ TmpPtr += SnpMode->HwAddressSize;\r
+\r
+ //\r
+ // The sender protocol address.\r
+ //\r
+ NetCopyMem (TmpPtr, ConfigData->StationAddress, ConfigData->SwAddressLength);\r
+ TmpPtr += ConfigData->SwAddressLength;\r
+\r
+ //\r
+ // The target hardware address.\r
+ //\r
+ NetCopyMem (\r
+ TmpPtr,\r
+ CacheEntry->Addresses[Hardware].AddressPtr,\r
+ SnpMode->HwAddressSize\r
+ );\r
+ TmpPtr += SnpMode->HwAddressSize;\r
+\r
+ //\r
+ // The target protocol address.\r
+ //\r
+ NetCopyMem (\r
+ TmpPtr,\r
+ CacheEntry->Addresses[Protocol].AddressPtr,\r
+ ConfigData->SwAddressLength\r
+ );\r
+\r
+ //\r
+ // Set all the fields of the TxData.\r
+ //\r
+ TxData->DestinationAddress = NULL;\r
+ TxData->SourceAddress = NULL;\r
+ TxData->ProtocolType = 0;\r
+ TxData->DataLength = TotalLength - SnpMode->MediaHeaderSize;\r
+ TxData->HeaderLength = (UINT16) SnpMode->MediaHeaderSize;\r
+ TxData->FragmentCount = 1;\r
+\r
+ TxData->FragmentTable[0].FragmentBuffer = Packet;\r
+ TxData->FragmentTable[0].FragmentLength = TotalLength;\r
+\r
+ //\r
+ // Associate the TxData with the TxToken.\r
+ //\r
+ TxToken->Packet.TxData = TxData;\r
+ TxToken->Status = EFI_NOT_READY;\r
+\r
+ //\r
+ // Send out this arp packet by Mnp.\r
+ //\r
+ Status = ArpService->Mnp->Transmit (ArpService->Mnp, TxToken);\r
+ if (EFI_ERROR (Status)) {\r
+ ARP_DEBUG_ERROR (("Mnp->Transmit failed, %r.\n", Status));\r
+ goto CLEAN_EXIT;\r
+ }\r
+\r
+ return;\r
+\r
+CLEAN_EXIT:\r
+\r
+ if (Packet != NULL) {\r
+ NetFreePool (Packet);\r
+ }\r
+\r
+ if (TxData != NULL) {\r
+ NetFreePool (TxData);\r
+ }\r
+\r
+ if (TxToken->Event != NULL) {\r
+ gBS->CloseEvent (TxToken->Event);\r
+ }\r
+\r
+ NetFreePool (TxToken);\r
+}\r
+\r
+\r
+/**\r
+ Delete the cache entries in the specified CacheTable, using the BySwAddress,\r
+ SwAddressType, AddressBuffer combination as the matching key, if Force is TRUE,\r
+ the cache is deleted event it's a static entry.\r
+\r
+ @param CacheTable Pointer to the cache table to do the deletion.\r
+ @param BySwAddress Delete the cache entry by software address or by\r
+ hardware address.\r
+ @param SwAddressType The software address used to do the deletion.\r
+ @param AddressBuffer Pointer to the buffer containing the address to\r
+ match for the deletion.\r
+ @param Force This deletion is forced or not.\r
+\r
+ @return The count of the deleted cache entries.\r
+\r
+**/\r
+STATIC\r
+UINTN\r
+ArpDeleteCacheEntryInTable (\r
+ IN NET_LIST_ENTRY *CacheTable,\r
+ IN BOOLEAN BySwAddress,\r
+ IN UINT16 SwAddressType,\r
+ IN UINT8 *AddressBuffer OPTIONAL,\r
+ IN BOOLEAN Force\r
+ )\r
+{\r
+ NET_LIST_ENTRY *Entry;\r
+ NET_LIST_ENTRY *NextEntry;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ UINTN Count;\r
+\r
+ Count = 0;\r
+\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, CacheTable) {\r
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
+\r
+ if ((CacheEntry->DefaultDecayTime == 0) && !Force) {\r
+ //\r
+ // It's a static entry and we are not forced to delete it, skip.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ if (BySwAddress) {\r
+ if (SwAddressType == CacheEntry->Addresses[Protocol].Type) {\r
+ //\r
+ // Protocol address type matched. Check the address.\r
+ //\r
+ if ((AddressBuffer == NULL) ||\r
+ (NetCompareMem (\r
+ AddressBuffer,\r
+ CacheEntry->Addresses[Protocol].AddressPtr,\r
+ CacheEntry->Addresses[Protocol].Length\r
+ ) == 0)) {\r
+ //\r
+ // Address matched.\r
+ //\r
+ goto MATCHED;\r
+ }\r
+ }\r
+ } else {\r
+ if ((AddressBuffer == NULL) ||\r
+ (NetCompareMem (\r
+ AddressBuffer,\r
+ CacheEntry->Addresses[Hardware].AddressPtr,\r
+ CacheEntry->Addresses[Hardware].Length\r
+ ) == 0)) {\r
+ //\r
+ // Address matched.\r
+ //\r
+ goto MATCHED;\r
+ }\r
+ }\r
+\r
+ continue;\r
+\r
+MATCHED:\r
+\r
+ //\r
+ // Delete this entry.\r
+ //\r
+ NetListRemoveEntry (&CacheEntry->List);\r
+ ASSERT (NetListIsEmpty (&CacheEntry->UserRequestList));\r
+ NetFreePool (CacheEntry);\r
+\r
+ Count++;\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+\r
+/**\r
+ Delete cache entries in all the cache tables.\r
+\r
+ @param Instance Pointer to the instance context data.\r
+ @param BySwAddress Delete the cache entry by software address or by\r
+ hardware address.\r
+ @param AddressBuffer Pointer to the buffer containing the address to\r
+ match for the deletion.\r
+ @param Force This deletion is forced or not.\r
+\r
+ @return The count of the deleted cache entries.\r
+\r
+**/\r
+UINTN\r
+ArpDeleteCacheEntry (\r
+ IN ARP_INSTANCE_DATA *Instance,\r
+ IN BOOLEAN BySwAddress,\r
+ IN UINT8 *AddressBuffer OPTIONAL,\r
+ IN BOOLEAN Force\r
+ )\r
+{\r
+ ARP_SERVICE_DATA *ArpService;\r
+ UINTN Count;\r
+\r
+ NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);\r
+\r
+ ArpService = Instance->ArpService;\r
+\r
+ //\r
+ // Delete the cache entries in the DeniedCacheTable.\r
+ //\r
+ Count = ArpDeleteCacheEntryInTable (\r
+ &ArpService->DeniedCacheTable,\r
+ BySwAddress,\r
+ Instance->ConfigData.SwAddressType,\r
+ AddressBuffer,\r
+ Force\r
+ );\r
+\r
+ //\r
+ // Delete the cache entries inthe ResolvedCacheTable.\r
+ //\r
+ Count += ArpDeleteCacheEntryInTable (\r
+ &ArpService->ResolvedCacheTable,\r
+ BySwAddress,\r
+ Instance->ConfigData.SwAddressType,\r
+ AddressBuffer,\r
+ Force\r
+ );\r
+\r
+ return Count;\r
+}\r
+\r
+\r
+/**\r
+ Cancel the arp request.\r
+\r
+ @param Instance Pointer to the instance context data.\r
+ @param TargetSwAddress Pointer to the buffer containing the target\r
+ software address to match the arp request.\r
+ @param UserEvent The user event used to notify this request\r
+ cancellation.\r
+\r
+ @return The count of the cancelled requests.\r
+\r
+**/\r
+UINTN\r
+ArpCancelRequest (\r
+ IN ARP_INSTANCE_DATA *Instance,\r
+ IN VOID *TargetSwAddress OPTIONAL,\r
+ IN EFI_EVENT UserEvent OPTIONAL\r
+ )\r
+{\r
+ ARP_SERVICE_DATA *ArpService;\r
+ NET_LIST_ENTRY *Entry;\r
+ NET_LIST_ENTRY *NextEntry;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ UINTN Count;\r
+\r
+ NET_CHECK_SIGNATURE (Instance, ARP_INSTANCE_DATA_SIGNATURE);\r
+\r
+ ArpService = Instance->ArpService;\r
+\r
+ Count = 0;\r
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &ArpService->PendingRequestTable) {\r
+ CacheEntry = NET_LIST_USER_STRUCT (Entry, ARP_CACHE_ENTRY, List);\r
+\r
+ if ((TargetSwAddress == NULL) ||\r
+ (NetCompareMem (\r
+ TargetSwAddress,\r
+ CacheEntry->Addresses[Protocol].AddressPtr,\r
+ CacheEntry->Addresses[Protocol].Length\r
+ ) == 0)) {\r
+ //\r
+ // This request entry matches the TargetSwAddress or all requests are to be\r
+ // cancelled as TargetSwAddress is NULL.\r
+ //\r
+ Count += ArpAddressResolved (CacheEntry, Instance, UserEvent);\r
+\r
+ if (NetListIsEmpty (&CacheEntry->UserRequestList)) {\r
+ //\r
+ // No user requests any more, remove this request cache entry.\r
+ //\r
+ NetListRemoveEntry (&CacheEntry->List);\r
+ NetFreePool (CacheEntry);\r
+ }\r
+ }\r
+ }\r
+\r
+ return Count;\r
+}\r
+\r
+\r
+/**\r
+ Find the cache entry in the cache table.\r
+\r
+ @param Instance Pointer to the instance context data.\r
+ @param BySwAddress Set to TRUE to look for matching software protocol\r
+ addresses. Set to FALSE to look for matching\r
+ hardware protocol addresses.\r
+ @param AddressBuffer Pointer to address buffer. Set to NULL to match\r
+ all addresses.\r
+ @param EntryLength The size of an entry in the entries buffer.\r
+ @param EntryCount The number of ARP cache entries that are found by\r
+ the specified criteria.\r
+ @param Entries Pointer to the buffer that will receive the ARP\r
+ cache entries.\r
+ @param Refresh Set to TRUE to refresh the timeout value of the\r
+ matching ARP cache entry.\r
+\r
+ @retval EFI_SUCCESS The requested ARP cache entries are copied into\r
+ the buffer.\r
+ @retval EFI_NOT_FOUND No matching entries found.\r
+ @retval EFI_OUT_OF_RESOURCE There is a memory allocation failure.\r
+\r
+**/\r
+EFI_STATUS\r
+ArpFindCacheEntry (\r
+ IN ARP_INSTANCE_DATA *Instance,\r
+ IN BOOLEAN BySwAddress,\r
+ IN VOID *AddressBuffer OPTIONAL,\r
+ OUT UINT32 *EntryLength OPTIONAL,\r
+ OUT UINT32 *EntryCount OPTIONAL,\r
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,\r
+ IN BOOLEAN Refresh\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ NET_ARP_ADDRESS MatchAddress;\r
+ FIND_OPTYPE FindOpType;\r
+ NET_LIST_ENTRY *StartEntry;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ NET_MAP FoundEntries;\r
+ UINT32 FoundCount;\r
+ EFI_ARP_FIND_DATA *FindData;\r
+ NET_LIST_ENTRY *CacheTable;\r
+\r
+ ArpService = Instance->ArpService;\r
+\r
+ //\r
+ // Init the FounEntries used to hold the found cache entries.\r
+ //\r
+ NetMapInit (&FoundEntries);\r
+\r
+ //\r
+ // Set the MatchAddress.\r
+ //\r
+ if (BySwAddress) {\r
+ MatchAddress.Type = Instance->ConfigData.SwAddressType;\r
+ MatchAddress.Length = Instance->ConfigData.SwAddressLength;\r
+ FindOpType = ByProtoAddress;\r
+ } else {\r
+ MatchAddress.Type = ArpService->SnpMode.IfType;\r
+ MatchAddress.Length = (UINT8)ArpService->SnpMode.HwAddressSize;\r
+ FindOpType = ByHwAddress;\r
+ }\r
+\r
+ MatchAddress.AddressPtr = AddressBuffer;\r
+\r
+ //\r
+ // Search the DeniedCacheTable\r
+ //\r
+ StartEntry = NULL;\r
+ while (TRUE) {\r
+ //\r
+ // Try to find the matched entries in the DeniedCacheTable.\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->DeniedCacheTable,\r
+ StartEntry,\r
+ FindOpType,\r
+ &MatchAddress,\r
+ &MatchAddress\r
+ );\r
+ if (CacheEntry == NULL) {\r
+ //\r
+ // Once the CacheEntry is NULL, there are no more matches.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Insert the found entry into the map.\r
+ //\r
+ NetMapInsertTail (\r
+ &FoundEntries,\r
+ (VOID *)CacheEntry,\r
+ (VOID *)&ArpService->DeniedCacheTable\r
+ );\r
+\r
+ //\r
+ // Let the next search start from this cache entry.\r
+ //\r
+ StartEntry = &CacheEntry->List;\r
+\r
+ if (Refresh) {\r
+ //\r
+ // Refresh the DecayTime if needed.\r
+ //\r
+ CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Search the ResolvedCacheTable\r
+ //\r
+ StartEntry = NULL;\r
+ while (TRUE) {\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->ResolvedCacheTable,\r
+ StartEntry,\r
+ FindOpType,\r
+ &MatchAddress,\r
+ &MatchAddress\r
+ );\r
+ if (CacheEntry == NULL) {\r
+ //\r
+ // Once the CacheEntry is NULL, there are no more matches.\r
+ //\r
+ break;\r
+ }\r
+\r
+ //\r
+ // Insert the found entry into the map.\r
+ //\r
+ NetMapInsertTail (\r
+ &FoundEntries,\r
+ (VOID *)CacheEntry,\r
+ (VOID *)&ArpService->ResolvedCacheTable\r
+ );\r
+\r
+ //\r
+ // Let the next search start from this cache entry.\r
+ //\r
+ StartEntry = &CacheEntry->List;\r
+\r
+ if (Refresh) {\r
+ //\r
+ // Refresh the DecayTime if needed.\r
+ //\r
+ CacheEntry->DecayTime = CacheEntry->DefaultDecayTime;\r
+ }\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ FoundCount = (UINT32) NetMapGetCount (&FoundEntries);\r
+ if (FoundCount == 0) {\r
+ Status = EFI_NOT_FOUND;\r
+ goto CLEAN_EXIT;\r
+ }\r
+\r
+ if (EntryLength != NULL) {\r
+ //\r
+ // Return the entry length.\r
+ //\r
+ *EntryLength = sizeof (EFI_ARP_FIND_DATA) + Instance->ConfigData.SwAddressLength +\r
+ ArpService->SnpMode.HwAddressSize;\r
+ }\r
+\r
+ if (EntryCount != NULL) {\r
+ //\r
+ // Return the found entry count.\r
+ //\r
+ *EntryCount = FoundCount;\r
+ }\r
+\r
+ if (Entries == NULL) {\r
+ goto CLEAN_EXIT;\r
+ }\r
+\r
+ //\r
+ // Allocate buffer to copy the found entries.\r
+ //\r
+ FindData = NetAllocatePool (FoundCount * (*EntryLength));\r
+ if (FindData == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpFindCacheEntry: Failed to allocate memory.\n"));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto CLEAN_EXIT;\r
+ }\r
+\r
+ //\r
+ // Return the address to the user.\r
+ //\r
+ *Entries = FindData;\r
+\r
+ //\r
+ // Dump the entries.\r
+ //\r
+ while (!NetMapIsEmpty (&FoundEntries)) {\r
+ //\r
+ // Get a cache entry from the map.\r
+ //\r
+ CacheEntry = NetMapRemoveHead (&FoundEntries, (VOID **)&CacheTable);\r
+\r
+ //\r
+ // Set the fields in FindData.\r
+ //\r
+ FindData->Size = *EntryLength;\r
+ FindData->DenyFlag = (BOOLEAN)(CacheTable == &ArpService->DeniedCacheTable);\r
+ FindData->StaticFlag = (BOOLEAN)(CacheEntry->DefaultDecayTime == 0);\r
+ FindData->HwAddressType = ArpService->SnpMode.IfType;\r
+ FindData->SwAddressType = Instance->ConfigData.SwAddressType;\r
+ FindData->HwAddressLength = (UINT8)ArpService->SnpMode.HwAddressSize;\r
+ FindData->SwAddressLength = Instance->ConfigData.SwAddressLength;\r
+\r
+ //\r
+ // Copy the software address.\r
+ //\r
+ NetCopyMem (\r
+ FindData + 1,\r
+ CacheEntry->Addresses[Protocol].AddressPtr,\r
+ FindData->SwAddressLength\r
+ );\r
+\r
+ //\r
+ // Copy the hardware address.\r
+ //\r
+ NetCopyMem (\r
+ (UINT8 *)(FindData + 1) + FindData->SwAddressLength,\r
+ CacheEntry->Addresses[Hardware].AddressPtr,\r
+ FindData->HwAddressLength\r
+ );\r
+\r
+ //\r
+ // Slip to the next FindData.\r
+ //\r
+ FindData = (EFI_ARP_FIND_DATA *)((UINT8 *)FindData + *EntryLength);\r
+ }\r
+\r
+CLEAN_EXIT:\r
+\r
+ NetMapClean (&FoundEntries);\r
+\r
+ return Status;\r
+}\r
+\r
--- /dev/null
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. 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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ ArpImpl.h
+
+Abstract:
+
+
+**/
+
+#ifndef _ARP_IMPL_H_
+#define _ARP_IMPL_H_
+
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Arp.h>\r
+#include <Protocol/ManagedNetwork.h>
+#include <Protocol/ServiceBinding.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>
+#include <Library/NetLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+
+#include "ArpDebug.h"
+
+#define ARP_ETHER_PROTO_TYPE 0x0806
+#define IPv4_ETHER_PROTO_TYPE 0x0800
+#define IPv6_ETHER_PROTO_TYPE 0x86DD
+
+#define ARP_OPCODE_REQUEST 0x0001
+#define ARP_OPCODE_REPLY 0x0002
+
+#define ARP_DEFAULT_TIMEOUT_VALUE (400 * TICKS_PER_SECOND)
+#define ARP_DEFAULT_RETRY_COUNT 2
+#define ARP_DEFAULT_RETRY_INTERVAL (5 * TICKS_PER_MS)
+#define ARP_PERIODIC_TIMER_INTERVAL (500 * TICKS_PER_MS)
+
+#pragma pack(1)
+typedef struct _ARP_HEAD {
+ UINT16 HwType;
+ UINT16 ProtoType;
+ UINT8 HwAddrLen;
+ UINT8 ProtoAddrLen;
+ UINT16 OpCode;
+} ARP_HEAD;
+#pragma pack()
+
+typedef struct _ARP_ADDRESS {
+ UINT8 *SenderHwAddr;
+ UINT8 *SenderProtoAddr;
+ UINT8 *TargetHwAddr;
+ UINT8 *TargetProtoAddr;
+} ARP_ADDRESS;
+
+#define MATCH_SW_ADDRESS 0x1
+#define MATCH_HW_ADDRESS 0x2
+
+typedef enum {
+ ByNone = 0,
+ ByProtoAddress = MATCH_SW_ADDRESS,
+ ByHwAddress = MATCH_HW_ADDRESS,
+ ByBoth = MATCH_SW_ADDRESS | MATCH_HW_ADDRESS
+} FIND_OPTYPE;
+
+#define ARP_INSTANCE_DATA_SIGNATURE EFI_SIGNATURE_32('A', 'R', 'P', 'I')
+
+#define ARP_INSTANCE_DATA_FROM_THIS(a) \
+ CR ( \
+ (a), \
+ ARP_INSTANCE_DATA, \
+ ArpProto, \
+ ARP_INSTANCE_DATA_SIGNATURE \
+ )
+
+typedef struct _ARP_SERVICE_DATA ARP_SERVICE_DATA;
+
+typedef struct _ARP_INSTANCE_DATA {
+ UINT32 Signature;
+ ARP_SERVICE_DATA *ArpService;
+ EFI_HANDLE Handle;
+ EFI_ARP_PROTOCOL ArpProto;
+ NET_LIST_ENTRY List;
+ EFI_ARP_CONFIG_DATA ConfigData;
+ BOOLEAN Configured;
+ BOOLEAN Destroyed;
+} ARP_INSTANCE_DATA;
+
+#define ARP_SERVICE_DATA_SIGNATURE EFI_SIGNATURE_32('A', 'R', 'P', 'S')
+
+#define ARP_SERVICE_DATA_FROM_THIS(a) \
+ CR ( \
+ (a), \
+ ARP_SERVICE_DATA, \
+ ServiceBinding, \
+ ARP_SERVICE_DATA_SIGNATURE \
+ )
+
+struct _ARP_SERVICE_DATA {
+ UINT32 Signature;
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
+
+ EFI_HANDLE MnpChildHandle;
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE ControllerHandle;
+
+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
+ EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData;
+ EFI_MANAGED_NETWORK_COMPLETION_TOKEN RxToken;
+
+ EFI_SIMPLE_NETWORK_MODE SnpMode;
+
+ NET_LOCK Lock;
+
+ UINTN ChildrenNumber;
+ NET_LIST_ENTRY ChildrenList;
+
+ NET_LIST_ENTRY PendingRequestTable;
+ NET_LIST_ENTRY DeniedCacheTable;
+ NET_LIST_ENTRY ResolvedCacheTable;
+
+ EFI_EVENT PeriodicTimer;
+};
+
+typedef struct _USER_REQUEST_CONTEXT {
+ NET_LIST_ENTRY List;
+ ARP_INSTANCE_DATA *Instance;
+ EFI_EVENT UserRequestEvent;
+ VOID *UserHwAddrBuffer;
+} USER_REQUEST_CONTEXT;
+
+#define ARP_MAX_PROTOCOL_ADDRESS_LEN sizeof(EFI_IP_ADDRESS)
+#define ARP_MAX_HARDWARE_ADDRESS_LEN sizeof(EFI_MAC_ADDRESS)
+
+typedef struct _NET_ARP_ADDRESS {
+ UINT16 Type;
+ UINT8 Length;
+ UINT8 *AddressPtr;
+ union {
+ UINT8 ProtoAddress[ARP_MAX_PROTOCOL_ADDRESS_LEN];
+ UINT8 HwAddress[ARP_MAX_HARDWARE_ADDRESS_LEN];
+ } Buffer;
+} NET_ARP_ADDRESS;
+
+typedef enum {
+ Hardware,
+ Protocol
+} ARP_ADDRESS_TYPE;
+
+typedef struct _ARP_CACHE_ENTRY {
+ NET_LIST_ENTRY List;
+
+ UINT32 RetryCount;
+ UINT32 DefaultDecayTime;
+ UINT32 DecayTime;
+ UINT32 NextRetryTime;
+
+ NET_ARP_ADDRESS Addresses[2];
+
+ NET_LIST_ENTRY UserRequestList;
+} ARP_CACHE_ENTRY;
+
+EFI_STATUS
+EFIAPI
+ArpConfigure (
+ IN EFI_ARP_PROTOCOL *This,
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpAdd (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN DenyFlag,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN VOID *TargetHwAddress OPTIONAL,
+ IN UINT32 TimeoutValue,
+ IN BOOLEAN Overwrite
+ );
+
+EFI_STATUS
+EFIAPI
+ArpFind (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL,
+ OUT UINT32 *EntryLength OPTIONAL,
+ OUT UINT32 *EntryCount OPTIONAL,
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
+ IN BOOLEAN Refresh
+ );
+
+EFI_STATUS
+EFIAPI
+ArpDelete (
+ IN EFI_ARP_PROTOCOL *This,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+ArpFlush (
+ IN EFI_ARP_PROTOCOL *This
+ );
+
+EFI_STATUS
+EFIAPI
+ArpRequest (
+ IN EFI_ARP_PROTOCOL *This,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT ResolvedEvent OPTIONAL,
+ OUT VOID *TargetHwAddress
+ );
+
+EFI_STATUS
+EFIAPI
+ArpCancel (
+ IN EFI_ARP_PROTOCOL *This,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT ResolvedEvent OPTIONAL
+ );
+
+EFI_STATUS
+ArpConfigureInstance (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL
+ );
+
+ARP_CACHE_ENTRY *
+ArpFindDeniedCacheEntry (
+ IN ARP_SERVICE_DATA *ArpService,
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
+ );
+
+ARP_CACHE_ENTRY *
+ArpFindNextCacheEntryInTable (
+ IN NET_LIST_ENTRY *CacheTable,
+ IN NET_LIST_ENTRY *StartEntry,
+ IN FIND_OPTYPE FindOpType,
+ IN NET_ARP_ADDRESS *ProtocolAddress OPTIONAL,
+ IN NET_ARP_ADDRESS *HardwareAddress OPTIONAL
+ );
+
+ARP_CACHE_ENTRY *
+ArpAllocCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance
+ );
+
+VOID
+ArpFillAddressInCacheEntry (
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN NET_ARP_ADDRESS *HwAddr OPTIONAL,
+ IN NET_ARP_ADDRESS *SwAddr OPTIONAL
+ );
+
+UINTN
+ArpAddressResolved (
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN ARP_INSTANCE_DATA *Instance OPTIONAL,
+ IN EFI_EVENT UserEvent OPTIONAL
+ );
+
+UINTN
+ArpDeleteCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN BOOLEAN BySwAddress,
+ IN UINT8 *AddressBuffer OPTIONAL,
+ IN BOOLEAN Force
+ );
+
+VOID
+ArpSendFrame (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN ARP_CACHE_ENTRY *CacheEntry,
+ IN UINT16 ArpOpCode
+ );
+
+VOID
+ArpInitInstance (
+ IN ARP_SERVICE_DATA *ArpService,
+ IN ARP_INSTANCE_DATA *Instance
+ );
+
+VOID
+EFIAPI
+ArpOnFrameRcvd (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+EFIAPI
+ArpOnFrameSent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+VOID
+EFIAPI
+ArpTimerHandler (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ );
+
+UINTN
+ArpCancelRequest (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN VOID *TargetSwAddress OPTIONAL,
+ IN EFI_EVENT UserEvent OPTIONAL
+ );
+
+EFI_STATUS
+ArpFindCacheEntry (
+ IN ARP_INSTANCE_DATA *Instance,
+ IN BOOLEAN BySwAddress,
+ IN VOID *AddressBuffer OPTIONAL,
+ OUT UINT32 *EntryLength OPTIONAL,
+ OUT UINT32 *EntryCount OPTIONAL,
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,
+ IN BOOLEAN Refresh
+ );
+
+#endif
+
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ ArpMain.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+#include "ArpImpl.h"\r
+\r
+\r
+/**\r
+ This function is used to assign a station address to the ARP cache for this instance\r
+ of the ARP driver. A call to this function with the ConfigData field set to NULL\r
+ will reset this ARP instance.\r
+\r
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
+ @param ConfigData Pointer to the EFI_ARP_CONFIG_DATA structure.\r
+\r
+ @retval EFI_SUCCESS The new station address was successfully\r
+ registered.\r
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
+ This is NULL. SwAddressLength is zero when\r
+ ConfigData is not NULL. StationAddress is NULL\r
+ when ConfigData is not NULL.\r
+ @retval EFI_ACCESS_DENIED The SwAddressType, SwAddressLength, or\r
+ StationAddress is different from the one that is\r
+ already registered.\r
+ @retval EFI_OUT_OF_RESOURCES Storage for the new StationAddress could not be\r
+ allocated.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpConfigure (\r
+ IN EFI_ARP_PROTOCOL *This,\r
+ IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_INSTANCE_DATA *Instance;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((ConfigData != NULL) &&\r
+ ((ConfigData->SwAddressLength == 0) ||\r
+ (ConfigData->StationAddress == NULL) ||\r
+ (ConfigData->SwAddressType <= 1500))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&Instance->ArpService->Lock))) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Configure this instance, the ConfigData has already passed the basic checks.\r
+ //\r
+ Status = ArpConfigureInstance (Instance, ConfigData);\r
+\r
+ NET_UNLOCK (&Instance->ArpService->Lock);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function is used to insert entries into the ARP cache.\r
+\r
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
+ @param DenyFlag Set to TRUE if this entry is a deny entry. Set to\r
+ FALSE if this entry is a normal entry.\r
+ @param TargetSwAddress Pointer to a protocol address to add (or deny).\r
+ May be set to NULL if DenyFlag is TRUE.\r
+ @param TargetHwAddress Pointer to a hardware address to add (or deny).\r
+ May be set to NULL if DenyFlag is TRUE.\r
+ @param TimeoutValue Time in 100-ns units that this entry will remain\r
+ in the ARP cache. A value of zero means that the\r
+ entry is permanent. A nonzero value will override\r
+ the one given by Configure() if the entry to be\r
+ added is a dynamic entry.\r
+ @param Overwrite If TRUE, the matching cache entry will be\r
+ overwritten with the supplied parameters. If\r
+ FALSE, EFI_ACCESS_DENIED is returned if the\r
+ corresponding cache entry already exists.\r
+\r
+ @retval EFI_SUCCESS The entry has been added or updated.\r
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
+ This is NULL. DenyFlag is FALSE and\r
+ TargetHwAddress is NULL. DenyFlag is FALSE and\r
+ TargetSwAddress is NULL. TargetHwAddress is NULL\r
+ and TargetSwAddress is NULL. Both TargetSwAddress\r
+ and TargetHwAddress are not NULL when DenyFlag is\r
+ TRUE.\r
+ @retval EFI_OUT_OF_RESOURCES The new ARP cache entry could not be allocated.\r
+ @retval EFI_ACCESS_DENIED The ARP cache entry already exists and Overwrite\r
+ is not true.\r
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpAdd (\r
+ IN EFI_ARP_PROTOCOL *This,\r
+ IN BOOLEAN DenyFlag,\r
+ IN VOID *TargetSwAddress OPTIONAL,\r
+ IN VOID *TargetHwAddress OPTIONAL,\r
+ IN UINT32 TimeoutValue,\r
+ IN BOOLEAN Overwrite\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_INSTANCE_DATA *Instance;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
+ NET_ARP_ADDRESS MatchAddress[2];\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((!DenyFlag) && ((TargetHwAddress == NULL) || (TargetSwAddress == NULL))) ||\r
+ (DenyFlag && (TargetHwAddress != NULL) && (TargetSwAddress != NULL)) ||\r
+ ((TargetHwAddress == NULL) && (TargetSwAddress == NULL))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
+\r
+ if (!Instance->Configured) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ ArpService = Instance->ArpService;\r
+ SnpMode = &Instance->ArpService->SnpMode;\r
+\r
+ //\r
+ // Fill the hardware address part in the MatchAddress.\r
+ //\r
+ MatchAddress[Hardware].Type = SnpMode->IfType;\r
+ MatchAddress[Hardware].Length = (UINT8) SnpMode->HwAddressSize;\r
+ MatchAddress[Hardware].AddressPtr = TargetHwAddress;\r
+\r
+ //\r
+ // Fill the software address part in the MatchAddress.\r
+ //\r
+ MatchAddress[Protocol].Type = Instance->ConfigData.SwAddressType;\r
+ MatchAddress[Protocol].Length = Instance->ConfigData.SwAddressLength;\r
+ MatchAddress[Protocol].AddressPtr = TargetSwAddress;\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // See whether the entry to add exists. Check the DeinedCacheTable first.\r
+ //\r
+ CacheEntry = ArpFindDeniedCacheEntry (\r
+ ArpService,\r
+ &MatchAddress[Protocol],\r
+ &MatchAddress[Hardware]\r
+ );\r
+\r
+ if (CacheEntry == NULL) {\r
+ //\r
+ // Check the ResolvedCacheTable\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->ResolvedCacheTable,\r
+ NULL,\r
+ ByBoth,\r
+ &MatchAddress[Protocol],\r
+ &MatchAddress[Hardware]\r
+ );\r
+ }\r
+\r
+ if ((CacheEntry != NULL) && !Overwrite) {\r
+ //\r
+ // The entry to add exists, if not Overwirte, deny this add request.\r
+ //\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ if ((CacheEntry == NULL) && (TargetSwAddress != NULL)) {\r
+ //\r
+ // Check whether there are pending requests matching the entry to be added.\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->PendingRequestTable,\r
+ NULL,\r
+ ByProtoAddress,\r
+ &MatchAddress[Protocol],\r
+ NULL\r
+ );\r
+ }\r
+\r
+ if (CacheEntry != NULL) {\r
+ //\r
+ // Remove it from the Table.\r
+ //\r
+ NetListRemoveEntry (&CacheEntry->List);\r
+ } else {\r
+ //\r
+ // It's a new entry, allocate memory for the entry.\r
+ //\r
+ CacheEntry = ArpAllocCacheEntry (Instance);\r
+\r
+ if (CacheEntry == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpAdd: Failed to allocate pool for CacheEntry.\n"));\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto UNLOCK_EXIT;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Overwrite these parameters.\r
+ //\r
+ CacheEntry->DefaultDecayTime = TimeoutValue;\r
+ CacheEntry->DecayTime = TimeoutValue;\r
+\r
+ //\r
+ // Fill in the addresses.\r
+ //\r
+ ArpFillAddressInCacheEntry (\r
+ CacheEntry,\r
+ &MatchAddress[Hardware],\r
+ &MatchAddress[Protocol]\r
+ );\r
+\r
+ //\r
+ // Inform the user if there is any.\r
+ //\r
+ ArpAddressResolved (CacheEntry, NULL, NULL);\r
+\r
+ //\r
+ // Add this CacheEntry to the corresponding CacheTable.\r
+ //\r
+ if (DenyFlag) {\r
+ NetListInsertHead (&ArpService->DeniedCacheTable, &CacheEntry->List);\r
+ } else {\r
+ NetListInsertHead (&ArpService->ResolvedCacheTable, &CacheEntry->List);\r
+ }\r
+\r
+UNLOCK_EXIT:\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function searches the ARP cache for matching entries and allocates a buffer into\r
+ which those entries are copied.\r
+\r
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
+ @param BySwAddress Set to TRUE to look for matching software protocol\r
+ addresses. Set to FALSE to look for matching\r
+ hardware protocol addresses.\r
+ @param AddressBuffer Pointer to address buffer. Set to NULL to match\r
+ all addresses.\r
+ @param EntryLength The size of an entry in the entries buffer.\r
+ @param EntryCount The number of ARP cache entries that are found by\r
+ the specified criteria.\r
+ @param Entries Pointer to the buffer that will receive the ARP\r
+ cache entries.\r
+ @param Refresh Set to TRUE to refresh the timeout value of the\r
+ matching ARP cache entry.\r
+\r
+ @retval EFI_SUCCESS The requested ARP cache entries were copied into\r
+ the buffer.\r
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
+ This is NULL. Both EntryCount and EntryLength are\r
+ NULL, when Refresh is FALSE.\r
+ @retval EFI_NOT_FOUND No matching entries were found.\r
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpFind (\r
+ IN EFI_ARP_PROTOCOL *This,\r
+ IN BOOLEAN BySwAddress,\r
+ IN VOID *AddressBuffer OPTIONAL,\r
+ OUT UINT32 *EntryLength OPTIONAL,\r
+ OUT UINT32 *EntryCount OPTIONAL,\r
+ OUT EFI_ARP_FIND_DATA **Entries OPTIONAL,\r
+ IN BOOLEAN Refresh\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_INSTANCE_DATA *Instance;\r
+ ARP_SERVICE_DATA *ArpService;\r
+\r
+ if ((This == NULL) ||\r
+ (!Refresh && (EntryCount == NULL) && (EntryLength == NULL)) ||\r
+ ((Entries != NULL) && ((EntryLength == NULL) || (EntryCount == NULL)))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
+ ArpService = Instance->ArpService;\r
+\r
+ if (!Instance->Configured) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // All the check passed, find the cache entries now.\r
+ //\r
+ Status = ArpFindCacheEntry (\r
+ Instance,\r
+ BySwAddress,\r
+ AddressBuffer,\r
+ EntryLength,\r
+ EntryCount,\r
+ Entries,\r
+ Refresh\r
+ );\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function removes specified ARP cache entries.\r
+\r
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
+ @param BySwAddress Set to TRUE to delete matching protocol addresses.\r
+ Set to FALSE to delete matching hardware\r
+ addresses.\r
+ @param AddressBuffer Pointer to the address buffer that is used as a\r
+ key to look for the cache entry. Set to NULL to\r
+ delete all entries.\r
+\r
+ @retval EFI_SUCCESS The entry was removed from the ARP cache.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ @retval EFI_NOT_FOUND The specified deletion key was not found.\r
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpDelete (\r
+ IN EFI_ARP_PROTOCOL *This,\r
+ IN BOOLEAN BySwAddress,\r
+ IN VOID *AddressBuffer OPTIONAL\r
+ )\r
+{\r
+ ARP_INSTANCE_DATA *Instance;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ UINTN Count;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
+\r
+ if (!Instance->Configured) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ ArpService = Instance->ArpService;\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Delete the specified cache entries.\r
+ //\r
+ Count = ArpDeleteCacheEntry (Instance, BySwAddress, AddressBuffer, TRUE);\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+ return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function delete all dynamic entries from the ARP cache that match the specified\r
+ software protocol type.\r
+\r
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
+\r
+ @retval EFI_SUCCESS The cache has been flushed.\r
+ @retval EFI_INVALID_PARAMETER This is NULL.\r
+ @retval EFI_NOT_FOUND There are no matching dynamic cache entries.\r
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpFlush (\r
+ IN EFI_ARP_PROTOCOL *This\r
+ )\r
+{\r
+ ARP_INSTANCE_DATA *Instance;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ UINTN Count;\r
+\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
+\r
+ if (!Instance->Configured) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ ArpService = Instance->ArpService;\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Delete the dynamic entries from the cache table.\r
+ //\r
+ Count = ArpDeleteCacheEntry (Instance, FALSE, NULL, FALSE);\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+ return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ This function tries to resolve the TargetSwAddress and optionally returns a\r
+ TargetHwAddress if it already exists in the ARP cache.\r
+\r
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
+ @param TargetSwAddress Pointer to the protocol address to resolve.\r
+ @param ResolvedEvent Pointer to the event that will be signaled when\r
+ the address is resolved or some error occurs.\r
+ @param TargetHwAddress Pointer to the buffer for the resolved hardware\r
+ address in network byte order.\r
+\r
+ @retval EFI_SUCCESS The data is copied from the ARP cache into the\r
+ TargetHwAddress buffer.\r
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
+ This is NULL. TargetHwAddress is NULL.\r
+ @retval EFI_ACCESS_DENIED The requested address is not present in the normal\r
+ ARP cache but is present in the deny address list.\r
+ Outgoing traffic to that address is forbidden.\r
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
+ @retval EFI_NOT_READY The request has been started and is not finished.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpRequest (\r
+ IN EFI_ARP_PROTOCOL *This,\r
+ IN VOID *TargetSwAddress OPTIONAL,\r
+ IN EFI_EVENT ResolvedEvent OPTIONAL,\r
+ OUT VOID *TargetHwAddress\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ARP_INSTANCE_DATA *Instance;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ EFI_SIMPLE_NETWORK_MODE *SnpMode;\r
+ ARP_CACHE_ENTRY *CacheEntry;\r
+ NET_ARP_ADDRESS HardwareAddress;\r
+ NET_ARP_ADDRESS ProtocolAddress;\r
+ USER_REQUEST_CONTEXT *RequestContext;\r
+\r
+ if ((This == NULL) || (TargetHwAddress == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
+\r
+ if (!Instance->Configured) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ ArpService = Instance->ArpService;\r
+ SnpMode = &ArpService->SnpMode;\r
+\r
+ if ((TargetSwAddress == NULL) ||\r
+ ((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&\r
+ IP4_IS_LOCAL_BROADCAST (*((UINT32 *)TargetSwAddress)))) {\r
+ //\r
+ // Return the hardware broadcast address.\r
+ //\r
+ NetCopyMem (TargetHwAddress, &SnpMode->BroadcastAddress, SnpMode->HwAddressSize);\r
+\r
+ goto SIGNAL_USER;\r
+ }\r
+\r
+ if ((Instance->ConfigData.SwAddressType == IPv4_ETHER_PROTO_TYPE) &&\r
+ IP4_IS_MULTICAST (NTOHL (*((UINT32 *)TargetSwAddress)))) {\r
+ //\r
+ // If the software address is an IPv4 multicast address, invoke Mnp to\r
+ // resolve the address.\r
+ //\r
+ Status = ArpService->Mnp->McastIpToMac (\r
+ ArpService->Mnp,\r
+ FALSE,\r
+ TargetSwAddress,\r
+ TargetHwAddress\r
+ );\r
+ goto SIGNAL_USER;\r
+ }\r
+\r
+ HardwareAddress.Type = SnpMode->IfType;\r
+ HardwareAddress.Length = (UINT8)SnpMode->HwAddressSize;\r
+ HardwareAddress.AddressPtr = NULL;\r
+\r
+ ProtocolAddress.Type = Instance->ConfigData.SwAddressType;\r
+ ProtocolAddress.Length = Instance->ConfigData.SwAddressLength;\r
+ ProtocolAddress.AddressPtr = TargetSwAddress;\r
+\r
+ //\r
+ // Initialize the TargetHwAddrss to a zero address.\r
+ //\r
+ NetZeroMem (TargetHwAddress, SnpMode->HwAddressSize);\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Check whether the software address is in the denied table.\r
+ //\r
+ CacheEntry = ArpFindDeniedCacheEntry (ArpService, &ProtocolAddress, NULL);\r
+ if (CacheEntry != NULL) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check whether the software address is already resolved.\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->ResolvedCacheTable,\r
+ NULL,\r
+ ByProtoAddress,\r
+ &ProtocolAddress,\r
+ NULL\r
+ );\r
+ if (CacheEntry != NULL) {\r
+ //\r
+ // Resolved, copy the address into the user buffer.\r
+ //\r
+ NetCopyMem (\r
+ TargetHwAddress,\r
+ CacheEntry->Addresses[Hardware].AddressPtr,\r
+ CacheEntry->Addresses[Hardware].Length\r
+ );\r
+\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ if (ResolvedEvent == NULL) {\r
+ Status = EFI_NOT_READY;\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ //\r
+ // Create a request context for this arp request.\r
+ //\r
+ RequestContext = NetAllocatePool (sizeof(USER_REQUEST_CONTEXT));\r
+ if (RequestContext == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for RequestContext failed.\n"));\r
+\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ RequestContext->Instance = Instance;\r
+ RequestContext->UserRequestEvent = ResolvedEvent;\r
+ RequestContext->UserHwAddrBuffer = TargetHwAddress;\r
+ NetListInit (&RequestContext->List);\r
+\r
+ //\r
+ // Check whether there is a same request.\r
+ //\r
+ CacheEntry = ArpFindNextCacheEntryInTable (\r
+ &ArpService->PendingRequestTable,\r
+ NULL,\r
+ ByProtoAddress,\r
+ &ProtocolAddress,\r
+ NULL\r
+ );\r
+ if (CacheEntry != NULL) {\r
+\r
+ CacheEntry->NextRetryTime = Instance->ConfigData.RetryTimeOut;\r
+ CacheEntry->RetryCount = Instance->ConfigData.RetryCount;\r
+ } else {\r
+ //\r
+ // Allocate a cache entry for this request.\r
+ //\r
+ CacheEntry = ArpAllocCacheEntry (Instance);\r
+ if (CacheEntry == NULL) {\r
+ ARP_DEBUG_ERROR (("ArpRequest: Allocate memory for CacheEntry failed.\n"));\r
+ NetFreePool (RequestContext);\r
+\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto UNLOCK_EXIT;\r
+ }\r
+\r
+ //\r
+ // Fill the software address.\r
+ //\r
+ ArpFillAddressInCacheEntry (CacheEntry, &HardwareAddress, &ProtocolAddress);\r
+\r
+ //\r
+ // Add this entry into the PendingRequestTable.\r
+ //\r
+ NetListInsertTail (&ArpService->PendingRequestTable, &CacheEntry->List);\r
+ }\r
+\r
+ //\r
+ // Link this request context into the cache entry.\r
+ //\r
+ NetListInsertHead (&CacheEntry->UserRequestList, &RequestContext->List);\r
+\r
+ //\r
+ // Send out the ARP Request frame.\r
+ //\r
+ ArpSendFrame (Instance, CacheEntry, ARP_OPCODE_REQUEST);\r
+ Status = EFI_NOT_READY;\r
+\r
+UNLOCK_EXIT:\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+SIGNAL_USER:\r
+\r
+ if ((ResolvedEvent != NULL) && (Status == EFI_SUCCESS)) {\r
+ gBS->SignalEvent (ResolvedEvent);\r
+ }\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ This function aborts the previous ARP request (identified by This, TargetSwAddress\r
+ and ResolvedEvent) that is issued by EFI_ARP_PROTOCOL.Request().\r
+\r
+ @param This Pointer to the EFI_ARP_PROTOCOL instance.\r
+ @param TargetSwAddress Pointer to the protocol address in previous\r
+ request session.\r
+ @param ResolvedEvent Pointer to the event that is used as the\r
+ notification event in previous request session.\r
+\r
+ @retval EFI_SUCCESS The pending request session(s) is/are aborted and\r
+ corresponding event(s) is/are signaled.\r
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r
+ This is NULL. TargetSwAddress is not NULL and\r
+ ResolvedEvent is NULL. TargetSwAddress is NULL and\r
+ ResolvedEvent is not NULL.\r
+ @retval EFI_NOT_STARTED The ARP driver instance has not been configured.\r
+ @retval EFI_NOT_FOUND The request is not issued by\r
+ EFI_ARP_PROTOCOL.Request().\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ArpCancel (\r
+ IN EFI_ARP_PROTOCOL *This,\r
+ IN VOID *TargetSwAddress OPTIONAL,\r
+ IN EFI_EVENT ResolvedEvent OPTIONAL\r
+ )\r
+{\r
+ ARP_INSTANCE_DATA *Instance;\r
+ ARP_SERVICE_DATA *ArpService;\r
+ UINTN Count;\r
+\r
+ if ((This == NULL) ||\r
+ ((TargetSwAddress != NULL) && (ResolvedEvent == NULL)) ||\r
+ ((TargetSwAddress == NULL) && (ResolvedEvent != NULL))) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = ARP_INSTANCE_DATA_FROM_THIS (This);\r
+\r
+ if (!Instance->Configured) {\r
+ return EFI_NOT_STARTED;\r
+ }\r
+\r
+ ArpService = Instance->ArpService;\r
+\r
+ if (EFI_ERROR (NET_TRYLOCK (&ArpService->Lock))) {\r
+ return EFI_ACCESS_DENIED;\r
+ }\r
+\r
+ //\r
+ // Cancel the specified request.\r
+ //\r
+ Count = ArpCancelRequest (Instance, TargetSwAddress, ResolvedEvent);\r
+\r
+ NET_UNLOCK (&ArpService->Lock);\r
+\r
+ return (Count == 0) ? EFI_NOT_FOUND : EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ ComponentName.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+#include "ArpDriver.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+ArpComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ArpComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+EFI_COMPONENT_NAME_PROTOCOL gArpComponentName = {\r
+ ArpComponentNameGetDriverName,\r
+ ArpComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+STATIC EFI_UNICODE_STRING_TABLE mArpDriverNameTable[] = {\r
+ { "eng", L"ARP Network Service Driver" },\r
+ { NULL, NULL }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ArpComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+ Arguments:\r
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ Language - A pointer to a three character ISO 639-2 language identifier.\r
+ This is the language of the driver name that that the caller\r
+ is requesting, and it must match one of the languages specified\r
+ in SupportedLanguages. The number of languages supported by a\r
+ driver is up to the driver writer.\r
+ DriverName - A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the driver specified by This in the language\r
+ specified by Language.\r
+\r
+ Returns:\r
+ EFI_SUCCES - The Unicode string for the Driver specified by This\r
+ and the language specified by Language was returned\r
+ in DriverName.\r
+ EFI_INVALID_PARAMETER - Language is NULL.\r
+ EFI_INVALID_PARAMETER - DriverName is NULL.\r
+ EFI_UNSUPPORTED - The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+--*/\r
+{\r
+ return LookupUnicodeString (\r
+ Language,\r
+ gArpComponentName.SupportedLanguages,\r
+ mArpDriverNameTable,\r
+ DriverName\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+ArpComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by an EFI Driver.\r
+\r
+ Arguments:\r
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ ControllerHandle - The handle of a controller that the driver specified by\r
+ This is managing. This handle specifies the controller\r
+ whose name is to be returned.\r
+ ChildHandle - The handle of the child controller to retrieve the name\r
+ of. This is an optional parameter that may be NULL. It\r
+ will be NULL for device drivers. It will also be NULL\r
+ for a bus drivers that wish to retrieve the name of the\r
+ bus controller. It will not be NULL for a bus driver\r
+ that wishes to retrieve the name of a child controller.\r
+ Language - A pointer to a three character ISO 639-2 language\r
+ identifier. This is the language of the controller name\r
+ that that the caller is requesting, and it must match one\r
+ of the languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up to the\r
+ driver writer.\r
+ ControllerName - A pointer to the Unicode string to return. This Unicode\r
+ string is the name of the controller specified by\r
+ ControllerHandle and ChildHandle in the language specified\r
+ by Language from the point of view of the driver specified\r
+ by This.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Unicode string for the user readable name in the\r
+ language specified by Language for the driver\r
+ specified by This was returned in DriverName.\r
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.\r
+ EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE.\r
+ EFI_INVALID_PARAMETER - Language is NULL.\r
+ EFI_INVALID_PARAMETER - ControllerName is NULL.\r
+ EFI_UNSUPPORTED - The driver specified by This is not currently managing\r
+ the controller specified by ControllerHandle and\r
+ ChildHandle.\r
+ EFI_UNSUPPORTED - The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+--*/\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ ComponentName.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+\r
+#include "Dhcp4Impl.h"\r
+\r
+//\r
+// EFI Component Name Functions\r
+//\r
+EFI_STATUS\r
+EFIAPI\r
+DhcpComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ );\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DhcpComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ );\r
+\r
+//\r
+// EFI Component Name Protocol\r
+//\r
+EFI_COMPONENT_NAME_PROTOCOL gDhcp4ComponentName = {\r
+ DhcpComponentNameGetDriverName,\r
+ DhcpComponentNameGetControllerName,\r
+ "eng"\r
+};\r
+\r
+static EFI_UNICODE_STRING_TABLE mDhcpDriverNameTable[] = {\r
+ {\r
+ "eng",\r
+ L"DHCP Protocol Driver"\r
+ },\r
+ {\r
+ NULL,\r
+ NULL\r
+ }\r
+};\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DhcpComponentNameGetDriverName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **DriverName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves a Unicode string that is the user readable name of the EFI Driver.\r
+\r
+ Arguments:\r
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ Language - A pointer to a three character ISO 639-2 language identifier.\r
+ This is the language of the driver name that that the caller\r
+ is requesting, and it must match one of the languages specified\r
+ in SupportedLanguages. The number of languages supported by a\r
+ driver is up to the driver writer.\r
+ DriverName - A pointer to the Unicode string to return. This Unicode string\r
+ is the name of the driver specified by This in the language\r
+ specified by Language.\r
+\r
+ Returns:\r
+ EFI_SUCCES - The Unicode string for the Driver specified by This\r
+ and the language specified by Language was returned\r
+ in DriverName.\r
+ EFI_INVALID_PARAMETER - Language is NULL.\r
+ EFI_INVALID_PARAMETER - DriverName is NULL.\r
+ EFI_UNSUPPORTED - The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+--*/\r
+{\r
+ return LookupUnicodeString (\r
+ Language,\r
+ gDhcp4ComponentName.SupportedLanguages,\r
+ mDhcpDriverNameTable,\r
+ DriverName\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+DhcpComponentNameGetControllerName (\r
+ IN EFI_COMPONENT_NAME_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_HANDLE ChildHandle OPTIONAL,\r
+ IN CHAR8 *Language,\r
+ OUT CHAR16 **ControllerName\r
+ )\r
+/*++\r
+\r
+ Routine Description:\r
+ Retrieves a Unicode string that is the user readable name of the controller\r
+ that is being managed by an EFI Driver.\r
+\r
+ Arguments:\r
+ This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.\r
+ ControllerHandle - The handle of a controller that the driver specified by\r
+ This is managing. This handle specifies the controller\r
+ whose name is to be returned.\r
+ ChildHandle - The handle of the child controller to retrieve the name\r
+ of. This is an optional parameter that may be NULL. It\r
+ will be NULL for device drivers. It will also be NULL\r
+ for a bus drivers that wish to retrieve the name of the\r
+ bus controller. It will not be NULL for a bus driver\r
+ that wishes to retrieve the name of a child controller.\r
+ Language - A pointer to a three character ISO 639-2 language\r
+ identifier. This is the language of the controller name\r
+ that that the caller is requesting, and it must match one\r
+ of the languages specified in SupportedLanguages. The\r
+ number of languages supported by a driver is up to the\r
+ driver writer.\r
+ ControllerName - A pointer to the Unicode string to return. This Unicode\r
+ string is the name of the controller specified by\r
+ ControllerHandle and ChildHandle in the language\r
+ specified by Language from the point of view of the\r
+ driver specified by This.\r
+\r
+ Returns:\r
+ EFI_SUCCESS - The Unicode string for the user readable name in the\r
+ language specified by Language for the driver\r
+ specified by This was returned in DriverName.\r
+ EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE.\r
+ EFI_INVALID_PARAMETER - ChildHandle isn't NULL and isn't a valid EFI_HANDLE.\r
+ EFI_INVALID_PARAMETER - Language is NULL.\r
+ EFI_INVALID_PARAMETER - ControllerName is NULL.\r
+ EFI_UNSUPPORTED - The driver specified by This is not currently\r
+ managing the controller specified by\r
+ ControllerHandle and ChildHandle.\r
+ EFI_UNSUPPORTED - The driver specified by This does not support the\r
+ language specified by Language.\r
+\r
+--*/\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}\r
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+Module Name:\r
+\r
+ Dhcp4Driver.c\r
+\r
+Abstract:\r
+\r
+\r
+**/\r
+\r
+#include "Dhcp4Impl.h"\r
+#include "Dhcp4Driver.h"\r
+\r
+EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding = {\r
+ Dhcp4DriverBindingSupported,\r
+ Dhcp4DriverBindingStart,\r
+ Dhcp4DriverBindingStop,\r
+ 0xa,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplete = {\r
+ Dhcp4ServiceBindingCreateChild,\r
+ Dhcp4ServiceBindingDestroyChild\r
+};\r
+\r
+//@MT: EFI_DRIVER_ENTRY_POINT (Dhcp4DriverEntryPoint)\r
+\r
+EFI_STATUS\r
+EFIAPI\r
+Dhcp4DriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+ Entry point of the DHCP driver to install various protocols.\r
+\r
+Arguments:\r
+\r
+ ImageHandle - The driver's image handle\r
+ SystemTable - The system table\r
+\r
+Returns:\r
+\r
+ EFI_SUCCESS - All the related protocols are installed.\r
+ Others - Failed to install the protocols.\r
+\r
+--*/\r
+{\r
+ return NetLibInstallAllDriverProtocols (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gDhcp4DriverBinding,\r
+ ImageHandle,\r
+ &gDhcp4ComponentName,\r
+ NULL,\r
+ NULL\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Test to see if DHCP driver supports the ControllerHandle.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to test\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCES This driver supports this device\r
+ @retval other This driver does not support this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dhcp4DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiUdp4ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Configure the default UDP child to receive all the DHCP traffics\r
+ on this network interface.\r
+\r
+ @param UdpIo The UDP IO port to configure\r
+ @param Context The context to the function\r
+\r
+ @retval EFI_SUCCESS The UDP IO port is successfully configured.\r
+ @retval Others Failed to configure the UDP child.\r
+\r
+**/\r
+EFI_STATUS\r
+DhcpConfigUdpIo (\r
+ IN UDP_IO_PORT *UdpIo,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_UDP4_CONFIG_DATA UdpConfigData;\r
+\r
+ UdpConfigData.AcceptBroadcast = TRUE;\r
+ UdpConfigData.AcceptPromiscuous = FALSE;\r
+ UdpConfigData.AcceptAnyPort = FALSE;\r
+ UdpConfigData.AllowDuplicatePort = TRUE;\r
+ UdpConfigData.TypeOfService = 0;\r
+ UdpConfigData.TimeToLive = 64;\r
+ UdpConfigData.DoNotFragment = FALSE;\r
+ UdpConfigData.ReceiveTimeout = 0;\r
+ UdpConfigData.TransmitTimeout = 0;\r
+\r
+ UdpConfigData.UseDefaultAddress = FALSE;\r
+ UdpConfigData.StationPort = DHCP_CLIENT_PORT;\r
+ UdpConfigData.RemotePort = DHCP_SERVER_PORT;\r
+\r
+ NetZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
+ NetZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+ NetZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ return UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Destory the DHCP service. The Dhcp4 service may be partly initialized,\r
+ or partly destoried. If a resource is destoried, it is marked as so in\r
+ case the destory failed and being called again later.\r
+\r
+ @param DhcpSb The DHCP service instance to destory.\r
+\r
+ @retval EFI_SUCCESS The DHCP service is successfully closed.\r
+\r
+**/\r
+EFI_STATUS\r
+Dhcp4CloseService (\r
+ IN DHCP_SERVICE *DhcpSb\r
+ )\r
+{\r
+ DhcpCleanLease (DhcpSb);\r
+\r
+ if (DhcpSb->UdpIo != NULL) {\r
+ UdpIoFreePort (DhcpSb->UdpIo);\r
+ DhcpSb->UdpIo = NULL;\r
+ }\r
+\r
+ if (DhcpSb->Timer != NULL) {\r
+ gBS->SetTimer (DhcpSb->Timer, TimerCancel, 0);\r
+ gBS->CloseEvent (DhcpSb->Timer);\r
+\r
+ DhcpSb->Timer = NULL;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+ Create a new DHCP service binding instance for the controller.\r
+\r
+ @param Controller The controller to install DHCP service binding\r
+ protocol onto\r
+ @param ImageHandle The driver's image handle\r
+ @param Service The variable to receive the created DHCP service\r
+ instance.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resource .\r
+ @retval EFI_SUCCESS The DHCP service instance is created.\r
+\r
+**/\r
+EFI_STATUS\r
+Dhcp4CreateService (\r
+ IN EFI_HANDLE Controller,\r
+ IN EFI_HANDLE ImageHandle,\r
+ OUT DHCP_SERVICE **Service\r
+ )\r
+{\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_STATUS Status;\r
+\r
+ *Service = NULL;\r
+ DhcpSb = NetAllocateZeroPool (sizeof (DHCP_SERVICE));\r
+\r
+ if (DhcpSb == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DhcpSb->Signature = DHCP_SERVICE_SIGNATURE;\r
+ DhcpSb->ServiceBinding = mDhcp4ServiceBindingTemplete;\r
+ DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
+ DhcpSb->InDestory = FALSE;\r
+ DhcpSb->Controller = Controller;\r
+ DhcpSb->Image = ImageHandle;\r
+ NetListInit (&DhcpSb->Children);\r
+ DhcpSb->DhcpState = Dhcp4Stopped;\r
+ DhcpSb->Xid = NET_RANDOM (NetRandomInitSeed ());\r
+\r
+ //\r
+ // Create various resources, UdpIo, Timer, and get Mac address\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ DhcpOnTimerTick,\r
+ DhcpSb,\r
+ &DhcpSb->Timer\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ DhcpSb->UdpIo = UdpIoCreatePort (Controller, ImageHandle, DhcpConfigUdpIo, NULL);\r
+\r
+ if (DhcpSb->UdpIo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ DhcpSb->HwLen = (UINT8) DhcpSb->UdpIo->SnpMode.HwAddressSize;\r
+ DhcpSb->HwType = DhcpSb->UdpIo->SnpMode.IfType;\r
+ CopyMem (&DhcpSb->Mac, &DhcpSb->UdpIo->SnpMode.CurrentAddress, sizeof (EFI_MAC_ADDRESS));\r
+\r
+ *Service = DhcpSb;\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ Dhcp4CloseService (DhcpSb);\r
+ NetFreePool (DhcpSb);\r
+\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Start this driver on ControllerHandle.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to bind driver to\r
+ @param RemainingDevicePath Optional parameter use to pick a specific child\r
+ device to start.\r
+\r
+ @retval EFI_SUCCES This driver is added to ControllerHandle\r
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
+ @retval other This driver does not support this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dhcp4DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // First: test for the DHCP4 Protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ if (Status == EFI_SUCCESS) {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ Status = Dhcp4CreateService (ControllerHandle, This->DriverBindingHandle, &DhcpSb);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Install the Dhcp4ServiceBinding Protocol onto ControlerHandle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ControllerHandle,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ &DhcpSb->ServiceBinding,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ return Status;\r
+\r
+ON_ERROR:\r
+ Dhcp4CloseService (DhcpSb);\r
+ NetFreePool (DhcpSb);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop this driver on ControllerHandle.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ControllerHandle Handle of device to stop driver on\r
+ @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
+ of children is zero stop the entire bus driver.\r
+ @param ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+ @retval EFI_SUCCES This driver is removed ControllerHandle\r
+ @retval other This driver was not removed from this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dhcp4DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer\r
+ )\r
+{\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ DHCP_SERVICE *DhcpSb;\r
+ DHCP_PROTOCOL *Instance;\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // DHCP driver opens UDP child, So, the ControllerHandle is the\r
+ // UDP child handle. locate the Nic handle first.\r
+ //\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);\r
+\r
+ if (NicHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NicHandle,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ (VOID **) &ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ NicHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);\r
+\r
+ if (DhcpSb->InDestory) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+ DhcpSb->InDestory = TRUE;\r
+\r
+ //\r
+ // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild\r
+ // may cause other child to be deleted.\r
+ //\r
+ while (!NetListIsEmpty (&DhcpSb->Children)) {\r
+ Instance = NET_LIST_HEAD (&DhcpSb->Children, DHCP_PROTOCOL, Link);\r
+ Dhcp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);\r
+ }\r
+\r
+ if (DhcpSb->NumChildren != 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ DhcpSb->ServiceState = DHCP_DESTORY;\r
+\r
+ Status = gBS->UninstallProtocolInterface (\r
+ NicHandle,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ ServiceBinding\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Dhcp4CloseService (DhcpSb);\r
+ NET_RESTORE_TPL (OldTpl);\r
+\r
+ NetFreePool (DhcpSb);\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ DhcpSb->InDestory = FALSE;\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Initialize a new DHCP child\r
+\r
+ @param DhcpSb The dhcp service instance\r
+ @param Instance The dhcp instance to initialize\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+DhcpInitProtocol (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN DHCP_PROTOCOL *Instance\r
+ )\r
+{\r
+ Instance->Signature = DHCP_PROTOCOL_SIGNATURE;\r
+ CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (EFI_DHCP4_PROTOCOL));\r
+ NetListInit (&Instance->Link);\r
+ Instance->Handle = NULL;\r
+ Instance->Service = DhcpSb;\r
+ Instance->InDestory = FALSE;\r
+ Instance->CompletionEvent = NULL;\r
+ Instance->RenewRebindEvent = NULL;\r
+ Instance->Token = NULL;\r
+}\r
+\r
+\r
+/**\r
+ Creates a child handle with a set of DHCP4 services.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ChildHandle Pointer to the handle of the child to create. If\r
+ it is NULL, then a new handle is created. If it\r
+ is not NULL, then the DHCP4 services are added to\r
+ the existing child handle.\r
+\r
+ @retval EFI_SUCCES The child handle was created with the DHCP4\r
+ services\r
+ @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the child\r
+ @retval other The child handle was not created\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dhcp4ServiceBindingCreateChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE *ChildHandle\r
+ )\r
+{\r
+ DHCP_SERVICE *DhcpSb;\r
+ DHCP_PROTOCOL *Instance;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ VOID *Udp4;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = NetAllocatePool (sizeof (*Instance));\r
+\r
+ if (Instance == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ DhcpSb = DHCP_SERVICE_FROM_THIS (This);\r
+ DhcpInitProtocol (DhcpSb, Instance);\r
+\r
+ //\r
+ // Install DHCP4 onto ChildHandle\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ ChildHandle,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ &Instance->Dhcp4Protocol,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ NetFreePool (Instance);\r
+ return Status;\r
+ }\r
+\r
+ Instance->Handle = *ChildHandle;\r
+\r
+ //\r
+ // Open the Udp4 protocol BY_CHILD.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ DhcpSb->UdpIo->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ (VOID **) &Udp4,\r
+ gDhcp4DriverBinding.DriverBindingHandle,\r
+ Instance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Instance->Handle,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ &Instance->Dhcp4Protocol,\r
+ NULL\r
+ );\r
+\r
+ NetFreePool (Instance);\r
+ return Status;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+\r
+ NetListInsertTail (&DhcpSb->Children, &Instance->Link);\r
+ DhcpSb->NumChildren++;\r
+\r
+ NET_RESTORE_TPL (OldTpl);\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Destroys a child handle with a set of DHCP4 services.\r
+\r
+ @param This Protocol instance pointer.\r
+ @param ChildHandle Handle of the child to destroy\r
+\r
+ @retval EFI_SUCCES The DHCP4 service is removed from the child handle\r
+ @retval EFI_UNSUPPORTED The child handle does not support the DHCP4\r
+ service\r
+ @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
+ @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
+ its DHCP4 services are being used.\r
+ @retval other The child handle was not destroyed\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Dhcp4ServiceBindingDestroyChild (\r
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ChildHandle\r
+ )\r
+{\r
+ DHCP_SERVICE *DhcpSb;\r
+ DHCP_PROTOCOL *Instance;\r
+ EFI_DHCP4_PROTOCOL *Dhcp;\r
+ EFI_TPL OldTpl;\r
+ EFI_STATUS Status;\r
+\r
+ if ((This == NULL) || (ChildHandle == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // Retrieve the private context data structures\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ChildHandle,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ (VOID **) &Dhcp,\r
+ gDhcp4DriverBinding.DriverBindingHandle,\r
+ ChildHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ Instance = DHCP_INSTANCE_FROM_THIS (Dhcp);\r
+ DhcpSb = DHCP_SERVICE_FROM_THIS (This);\r
+\r
+ if (Instance->Service != DhcpSb) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ //\r
+ // A child can be destoried more than once. For example,\r
+ // Dhcp4DriverBindingStop will destory all of its children.\r
+ // when caller driver is being stopped, it will destory the\r
+ // dhcp child it opens.\r
+ //\r
+ if (Instance->InDestory) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+ Instance->InDestory = TRUE;\r
+\r
+ //\r
+ // Close the Udp4 protocol.\r
+ //\r
+ gBS->CloseProtocol (\r
+ DhcpSb->UdpIo->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ gDhcp4DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+\r
+ //\r
+ // Uninstall the DHCP4 protocol first to enable a top down destruction.\r
+ //\r
+ Status = gBS->UninstallProtocolInterface (\r
+ ChildHandle,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ Dhcp\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Instance->InDestory = FALSE;\r
+\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return Status;\r
+ }\r
+\r
+ if (DhcpSb->ActiveChild == Instance) {\r
+ DhcpYieldControl (DhcpSb);\r
+ }\r
+\r
+ NetListRemoveEntry (&Instance->Link);\r
+ DhcpSb->NumChildren--;\r
+\r
+ NET_RESTORE_TPL (OldTpl);\r
+\r
+ NetFreePool (Instance);\r
+ return EFI_SUCCESS;\r
+}\r
--- /dev/null
+/** @file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. 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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Dhcp4Driver.h
+
+Abstract:
+
+ Header for the DHCP4 driver
+
+
+**/
+
+#ifndef __EFI_DHCP4_DRIVER_H__
+#define __EFI_DHCP4_DRIVER_H__
+
+extern EFI_COMPONENT_NAME_PROTOCOL gDhcp4ComponentName;
+
+EFI_STATUS
+EFIAPI
+Dhcp4DriverBindingSupported (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+Dhcp4DriverBindingStart (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
+ );
+
+EFI_STATUS
+EFIAPI
+Dhcp4DriverBindingStop (
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NumberOfChildren,
+ IN EFI_HANDLE *ChildHandleBuffer
+ );
+
+EFI_STATUS
+EFIAPI
+Dhcp4ServiceBindingCreateChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE *ChildHandle
+ );
+
+EFI_STATUS
+EFIAPI
+Dhcp4ServiceBindingDestroyChild (
+ IN EFI_SERVICE_BINDING_PROTOCOL *This,
+ IN EFI_HANDLE ChildHandle
+ );
+
+#endif
--- /dev/null
+#/** @file\r
+# Component name for module Dhcp4\r
+#\r
+# Copyright (c) 2007, Intel Corporation\r
+#\r
+# All rights reserved. This program and the accompanying materials\r
+# are licensed and made available under the terms and conditions of the BSD License\r
+# which accompanies this distribution. The full text of the license may be found at\r
+# http://opensource.org/licenses/bsd-license.php\r
+#\r
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+#\r
+#\r
+#**/\r
+\r
+[Defines]\r
+ INF_VERSION = 0x00010005\r
+ BASE_NAME = Dhcp4Dxe\r
+ FILE_GUID = 94734718-0BBC-47fb-96A5-EE7A5AE6A2AD\r
+ MODULE_TYPE = DXE_DRIVER\r
+ VERSION_STRING = 1.0\r
+ EDK_RELEASE_VERSION = 0x00020000\r
+ EFI_SPECIFICATION_VERSION = 0x00020000\r
+\r
+ ENTRY_POINT = Dhcp4DriverEntryPoint\r
+\r
+#\r
+# The following information is for reference only and not required by the build tools.\r
+#\r
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC\r
+#\r
+\r
+[Sources.common]\r
+ Dhcp4Impl.c\r
+ Dhcp4Io.c\r
+ Dhcp4Io.h\r
+ ComponentName.c\r
+ Dhcp4Driver.h\r
+ Dhcp4Driver.c\r
+ Dhcp4Option.c\r
+ Dhcp4Option.h\r
+ Dhcp4Impl.h\r
+\r
+[Packages]\r
+ MdePkg/MdePkg.dec\r
+ MdeModulePkg/MdeModulePkg.dec\r
+\r
+\r
+[LibraryClasses]\r
+ BaseLib\r
+ UefiLib\r
+ UefiBootServicesTableLib\r
+ UefiDriverEntryPoint\r
+ DebugLib\r
+ NetLib\r
+ UdpIoLib\r
+\r
+\r
+[Protocols]\r
+ gEfiUdp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDhcp4ServiceBindingProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiUdp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+ gEfiDhcp4ProtocolGuid # PROTOCOL ALWAYS_CONSUMED\r
+\r
--- /dev/null
+<ModuleSurfaceArea xmlns="http://www.TianoCore.org/2006/Edk2.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">\r
+ <MsaHeader>\r
+ <ModuleName>Dhcp4Dxe</ModuleName>\r
+ <ModuleType>DXE_DRIVER</ModuleType>\r
+ <GuidValue>94734718-0BBC-47fb-96A5-EE7A5AE6A2AD</GuidValue>\r
+ <Version>1.0</Version>\r
+ <Abstract>Component name for module Dhcp4</Abstract>\r
+ <Description>FIX ME!</Description>\r
+ <Copyright>Copyright (c) 2007, Intel Corporation. All rights reserved.</Copyright>\r
+ <License>All rights reserved. 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
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.</License>\r
+ <Specification>FRAMEWORK_BUILD_PACKAGING_SPECIFICATION 0x00000052</Specification>\r
+ </MsaHeader>\r
+ <ModuleDefinitions>\r
+ <SupportedArchitectures>IA32 X64 IPF EBC</SupportedArchitectures>\r
+ <BinaryModule>false</BinaryModule>\r
+ <OutputFileBasename>Dhcp4Dxe</OutputFileBasename>\r
+ </ModuleDefinitions>\r
+ <LibraryClassDefinitions>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>DebugLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiDriverEntryPoint</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiBootServicesTableLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>UefiLib</Keyword>\r
+ </LibraryClass>\r
+ <LibraryClass Usage="ALWAYS_CONSUMED">\r
+ <Keyword>BaseLib</Keyword>\r
+ </LibraryClass>\r
+ </LibraryClassDefinitions>\r
+ <SourceFiles>\r
+ <Filename>Dhcp4Impl.h</Filename>\r
+ <Filename>Dhcp4Option.h</Filename>\r
+ <Filename>Dhcp4Option.c</Filename>\r
+ <Filename>Dhcp4Driver.c</Filename>\r
+ <Filename>Dhcp4Driver.h</Filename>\r
+ <Filename>ComponentName.c</Filename>\r
+ <Filename>Dhcp4Io.h</Filename>\r
+ <Filename>Dhcp4Io.c</Filename>\r
+ <Filename>Dhcp4Impl.c</Filename>\r
+ </SourceFiles>\r
+ <PackageDependencies>\r
+ <Package PackageGuid="5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec"/>\r
+ <Package PackageGuid="68169ab0-d41b-4009-9060-292c253ac43d"/>\r
+ </PackageDependencies>\r
+ <Protocols>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDhcp4ProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiUdp4ProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiDhcp4ServiceBindingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ <Protocol Usage="ALWAYS_CONSUMED">\r
+ <ProtocolCName>gEfiUdp4ServiceBindingProtocolGuid</ProtocolCName>\r
+ </Protocol>\r
+ </Protocols>\r
+ <Externs>\r
+ <Specification>EFI_SPECIFICATION_VERSION 0x00020000</Specification>\r
+ <Specification>EDK_RELEASE_VERSION 0x00020000</Specification>\r
+ <Extern>\r
+ <ModuleEntryPoint>Dhcp4DriverEntryPoint</ModuleEntryPoint>\r
+ </Extern>\r
+ </Externs>\r
+</ModuleSurfaceArea>
\ No newline at end of file
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Dhcp4Impl.c\r
+\r
+Abstract:\r
+\r
+ This file implement the EFI_DHCP4_PROTOCOL interface.\r
+\r
+\r
+**/\r
+\r
+\r
+#include "Dhcp4Impl.h"\r
+\r
+\r
+/**\r
+ Get the current operation parameter and lease for the network interface.\r
+\r
+ @param This The DHCP protocol instance\r
+ @param Dhcp4ModeData The variable to save the DHCP mode data.\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid\r
+ @retval EFI_SUCCESS The Dhcp4ModeData is updated with the current\r
+ operation parameter.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4GetModeData (\r
+ IN EFI_DHCP4_PROTOCOL *This,\r
+ OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData\r
+ )\r
+{\r
+ DHCP_PROTOCOL *Instance;\r
+ DHCP_SERVICE *DhcpSb;\r
+ DHCP_PARAMETER *Para;\r
+ EFI_TPL OldTpl;\r
+ IP4_ADDR Ip;\r
+\r
+ //\r
+ // First validate the parameters.\r
+ //\r
+ if ((This == NULL) || (Dhcp4ModeData == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = DHCP_INSTANCE_FROM_THIS (This);\r
+\r
+ if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+ DhcpSb = Instance->Service;\r
+\r
+ //\r
+ // Caller can use GetModeData to retrieve current DHCP states\r
+ // no matter whether it is the active child or not.\r
+ //\r
+ Dhcp4ModeData->State = DhcpSb->DhcpState;\r
+ CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (EFI_DHCP4_CONFIG_DATA));\r
+ CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (EFI_MAC_ADDRESS));\r
+\r
+ Ip = HTONL (DhcpSb->ClientAddr);\r
+ NetCopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ Ip = HTONL (DhcpSb->Netmask);\r
+ NetCopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ Ip = HTONL (DhcpSb->ServerAddr);\r
+ NetCopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ Para = DhcpSb->Para;\r
+\r
+ if (Para != NULL) {\r
+ Ip = HTONL (Para->Router);\r
+ NetCopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+ Dhcp4ModeData->LeaseTime = Para->Lease;\r
+ } else {\r
+ NetZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
+ Dhcp4ModeData->LeaseTime = 0xffffffff;\r
+ }\r
+\r
+ Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;\r
+\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Free the resource related to the configure parameters.\r
+ DHCP driver will make a copy of the user's configure\r
+ such as the time out value.\r
+\r
+ @param Config The DHCP configure data\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+DhcpCleanConfigure (\r
+ IN EFI_DHCP4_CONFIG_DATA *Config\r
+ )\r
+{\r
+ UINT32 Index;\r
+\r
+ if (Config->DiscoverTimeout != NULL) {\r
+ NetFreePool (Config->DiscoverTimeout);\r
+ }\r
+\r
+ if (Config->RequestTimeout != NULL) {\r
+ NetFreePool (Config->RequestTimeout);\r
+ }\r
+\r
+ if (Config->OptionList != NULL) {\r
+ for (Index = 0; Index < Config->OptionCount; Index++) {\r
+ if (Config->OptionList[Index] != NULL) {\r
+ NetFreePool (Config->OptionList[Index]);\r
+ }\r
+ }\r
+\r
+ NetFreePool (Config->OptionList);\r
+ }\r
+\r
+ NetZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));\r
+}\r
+\r
+\r
+/**\r
+ Allocate memory for configure parameter such as timeout value for Dst,\r
+ then copy the configure parameter from Src to Dst.\r
+\r
+ @param Dst The destination DHCP configure data.\r
+ @param Src The source DHCP configure data.\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
+ @retval EFI_SUCCESS The configure is copied.\r
+\r
+**/\r
+EFI_STATUS\r
+DhcpCopyConfigure (\r
+ IN EFI_DHCP4_CONFIG_DATA *Dst,\r
+ IN EFI_DHCP4_CONFIG_DATA *Src\r
+ )\r
+{\r
+ EFI_DHCP4_PACKET_OPTION **DstOptions;\r
+ EFI_DHCP4_PACKET_OPTION **SrcOptions;\r
+ INTN Len;\r
+ UINT32 Index;\r
+\r
+ CopyMem (Dst, Src, sizeof (EFI_DHCP4_CONFIG_DATA));\r
+ Dst->DiscoverTimeout = NULL;\r
+ Dst->RequestTimeout = NULL;\r
+ Dst->OptionList = NULL;\r
+\r
+ //\r
+ // Allocate a memory then copy DiscoverTimeout to it\r
+ //\r
+ if (Src->DiscoverTimeout != NULL) {\r
+ Len = Src->DiscoverTryCount * sizeof (UINT32);\r
+ Dst->DiscoverTimeout = NetAllocatePool (Len);\r
+\r
+ if (Dst->DiscoverTimeout == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (Index = 0; Index < Src->DiscoverTryCount; Index++) {\r
+ Dst->DiscoverTimeout[Index] = NET_MAX (Src->DiscoverTimeout[Index], 1);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Allocate a memory then copy RequestTimeout to it\r
+ //\r
+ if (Src->RequestTimeout != NULL) {\r
+ Len = Src->RequestTryCount * sizeof (UINT32);\r
+ Dst->RequestTimeout = NetAllocatePool (Len);\r
+\r
+ if (Dst->RequestTimeout == NULL) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ for (Index = 0; Index < Src->RequestTryCount; Index++) {\r
+ Dst->RequestTimeout[Index] = NET_MAX (Src->RequestTimeout[Index], 1);\r
+ }\r
+ }\r
+\r
+ //\r
+ // Allocate an array of dhcp option point, then allocate memory\r
+ // for each option and copy the source option to it\r
+ //\r
+ if (Src->OptionList != NULL) {\r
+ Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);\r
+ Dst->OptionList = NetAllocateZeroPool (Len);\r
+\r
+ if (Dst->OptionList == NULL) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ DstOptions = Dst->OptionList;\r
+ SrcOptions = Src->OptionList;\r
+\r
+ for (Index = 0; Index < Src->OptionCount; Index++) {\r
+ Len = sizeof (EFI_DHCP4_PACKET_OPTION) + NET_MAX (SrcOptions[Index]->Length - 1, 0);\r
+\r
+ DstOptions[Index] = NetAllocatePool (Len);\r
+\r
+ if (DstOptions[Index] == NULL) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ NetCopyMem (DstOptions[Index], SrcOptions[Index], Len);\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ DhcpCleanConfigure (Dst);\r
+ return EFI_OUT_OF_RESOURCES;\r
+}\r
+\r
+\r
+/**\r
+ Give up the control of the DHCP service to let other child\r
+ resume. Don't change the service's DHCP state and the Client\r
+ address and option list configure as required by RFC2131.\r
+\r
+ @param DhcpSb The DHCP service instance.\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+DhcpYieldControl (\r
+ IN DHCP_SERVICE *DhcpSb\r
+ )\r
+{\r
+ EFI_DHCP4_CONFIG_DATA *Config;\r
+ DHCP_PROTOCOL *Instance;\r
+\r
+ Instance = DhcpSb->ActiveChild;\r
+ Config = &DhcpSb->ActiveConfig;\r
+\r
+ DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
+ DhcpSb->ActiveChild = NULL;\r
+\r
+ if (Config->DiscoverTimeout != NULL) {\r
+ NetFreePool (Config->DiscoverTimeout);\r
+\r
+ Config->DiscoverTryCount = 0;\r
+ Config->DiscoverTimeout = NULL;\r
+ }\r
+\r
+ if (Config->RequestTimeout != NULL) {\r
+ NetFreePool (Config->RequestTimeout);\r
+\r
+ Config->RequestTryCount = 0;\r
+ Config->RequestTimeout = NULL;\r
+ }\r
+\r
+ Config->Dhcp4Callback = NULL;\r
+ Config->CallbackContext = NULL;\r
+}\r
+\r
+\r
+/**\r
+ Configure the DHCP protocol instance and its underlying DHCP service\r
+ for operation. If Dhcp4CfgData is NULL and the child is currently\r
+ controlling the DHCP service, release the control.\r
+\r
+ @param This The DHCP protocol instance\r
+ @param Dhcp4CfgData The DHCP configure data.\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_ACCESS_DENIED The service isn't in one of configurable states,\r
+ or there is already an active child.\r
+ @retval EFI_OUT_OF_RESOURCE Failed to allocate some resources.\r
+ @retval EFI_SUCCESS The child is configured.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Configure (\r
+ IN EFI_DHCP4_PROTOCOL *This,\r
+ IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL\r
+ )\r
+{\r
+ EFI_DHCP4_CONFIG_DATA *Config;\r
+ DHCP_PROTOCOL *Instance;\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+ UINT32 Index;\r
+ IP4_ADDR Ip;\r
+\r
+ //\r
+ // First validate the parameters\r
+ //\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Dhcp4CfgData != NULL) {\r
+ if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));\r
+\r
+ if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+\r
+ Instance = DHCP_INSTANCE_FROM_THIS (This);\r
+\r
+ if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+\r
+ DhcpSb = Instance->Service;\r
+ Config = &DhcpSb->ActiveConfig;\r
+\r
+ Status = EFI_ACCESS_DENIED;\r
+\r
+ if ((DhcpSb->DhcpState != Dhcp4Stopped) &&\r
+ (DhcpSb->DhcpState != Dhcp4Init) &&\r
+ (DhcpSb->DhcpState != Dhcp4InitReboot) &&\r
+ (DhcpSb->DhcpState != Dhcp4Bound)) {\r
+\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (Dhcp4CfgData != NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ DhcpCleanConfigure (Config);\r
+\r
+ if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ DhcpSb->UserOptionLen = 0;\r
+\r
+ for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {\r
+ DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;\r
+ }\r
+\r
+ DhcpSb->ActiveChild = Instance;\r
+\r
+ if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
+ DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);\r
+\r
+ if (DhcpSb->ClientAddr != 0) {\r
+ DhcpSb->DhcpState = Dhcp4InitReboot;\r
+ } else {\r
+ DhcpSb->DhcpState = Dhcp4Init;\r
+ }\r
+ }\r
+\r
+ DhcpSb->ServiceState = DHCP_CONFIGED;\r
+ Status = EFI_SUCCESS;\r
+\r
+ } else if (DhcpSb->ActiveChild == Instance) {\r
+ Status = EFI_SUCCESS;\r
+ DhcpYieldControl (DhcpSb);\r
+ }\r
+\r
+ON_EXIT:\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Start the DHCP process.\r
+\r
+ @param This The DHCP protocol instance\r
+ @param CompletionEvent The event to signal is address is acquired.\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_NOT_STARTED The protocol hasn't been configured.\r
+ @retval EFI_ALREADY_STARTED The DHCP process has already been started.\r
+ @retval EFI_SUCCESS The DHCP process is started.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Start (\r
+ IN EFI_DHCP4_PROTOCOL *This,\r
+ IN EFI_EVENT CompletionEvent OPTIONAL\r
+ )\r
+{\r
+ DHCP_PROTOCOL *Instance;\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // First validate the parameters\r
+ //\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = DHCP_INSTANCE_FROM_THIS (This);\r
+\r
+ if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+ DhcpSb = Instance->Service;\r
+\r
+ if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
+ Status = EFI_NOT_STARTED;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {\r
+ Status = EFI_ALREADY_STARTED;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
+\r
+ if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Start/Restart the receiving.\r
+ //\r
+ Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
+\r
+ if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Instance->CompletionEvent = CompletionEvent;\r
+\r
+ //\r
+ // Restore the TPL now, don't call poll function at NET_TPL_LOCK.\r
+ //\r
+ NET_RESTORE_TPL (OldTpl);\r
+\r
+ if (CompletionEvent == NULL) {\r
+ while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
+ DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
+ }\r
+\r
+ return DhcpSb->IoStatus;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Request an extra manual renew/rebind.\r
+\r
+ @param This The DHCP protocol instance\r
+ @param RebindRequest TRUE if request a rebind, otherwise renew it\r
+ @param CompletionEvent Event to signal when complete\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid\r
+ @retval EFI_NOT_STARTED The DHCP protocol hasn't been started.\r
+ @retval EFI_ACCESS_DENIED The DHCP protocol isn't in Bound state.\r
+ @retval EFI_SUCCESS The DHCP is renewed/rebound.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4RenewRebind (\r
+ IN EFI_DHCP4_PROTOCOL *This,\r
+ IN BOOLEAN RebindRequest,\r
+ IN EFI_EVENT CompletionEvent OPTIONAL\r
+ )\r
+{\r
+ DHCP_PROTOCOL *Instance;\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // First validate the parameters\r
+ //\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = DHCP_INSTANCE_FROM_THIS (This);\r
+\r
+ if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+ DhcpSb = Instance->Service;\r
+\r
+ if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
+ Status = EFI_NOT_STARTED;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if (DhcpSb->DhcpState != Dhcp4Bound) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ if (DHCP_IS_BOOTP (DhcpSb->Para)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Transit the states then send a extra DHCP request\r
+ //\r
+ if (!RebindRequest) {\r
+ DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);\r
+ } else {\r
+ DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);\r
+ }\r
+\r
+ Status = DhcpSendMessage (\r
+ DhcpSb,\r
+ DhcpSb->Selected,\r
+ DhcpSb->Para,\r
+ DHCP_MSG_REQUEST,\r
+ "Extra renew/rebind by the application"\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ DhcpSb->ExtraRefresh = TRUE;\r
+ DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
+ Instance->RenewRebindEvent = CompletionEvent;\r
+\r
+ NET_RESTORE_TPL (OldTpl);\r
+\r
+ if (CompletionEvent == NULL) {\r
+ while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
+ DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
+ }\r
+\r
+ return DhcpSb->IoStatus;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Release the current acquired lease.\r
+\r
+ @param This The DHCP protocol instance\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid\r
+ @retval EFI_DEVICE_ERROR Failed to transmit the DHCP release packet\r
+ @retval EFI_ACCESS_DENIED The DHCP service isn't in one of the connected\r
+ state.\r
+ @retval EFI_SUCCESS The lease is released.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Release (\r
+ IN EFI_DHCP4_PROTOCOL *This\r
+ )\r
+{\r
+ DHCP_PROTOCOL *Instance;\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_STATUS Status;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // First validate the parameters\r
+ //\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = DHCP_INSTANCE_FROM_THIS (This);\r
+\r
+ if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+ DhcpSb = Instance->Service;\r
+\r
+ if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {\r
+ Status = DhcpSendMessage (\r
+ DhcpSb,\r
+ DhcpSb->Selected,\r
+ DhcpSb->Para,\r
+ DHCP_MSG_RELEASE,\r
+ NULL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+\r
+ DhcpCleanLease (DhcpSb);\r
+\r
+ON_EXIT:\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Stop the current DHCP process. After this, other DHCP child\r
+ can gain control of the service, configure and use it.\r
+\r
+ @param This The DHCP protocol instance\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
+ @retval EFI_SUCCESS The DHCP process is stopped.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Stop (\r
+ IN EFI_DHCP4_PROTOCOL *This\r
+ )\r
+{\r
+ DHCP_PROTOCOL *Instance;\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_TPL OldTpl;\r
+\r
+ //\r
+ // First validate the parameters\r
+ //\r
+ if (This == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = DHCP_INSTANCE_FROM_THIS (This);\r
+\r
+ if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+ DhcpSb = Instance->Service;\r
+\r
+ DhcpCleanLease (DhcpSb);\r
+\r
+ DhcpSb->DhcpState = Dhcp4Stopped;\r
+ DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
+\r
+ NET_RESTORE_TPL (OldTpl);\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Build a new DHCP packet from the seed packet. Options may be deleted or\r
+ appended. The caller should free the NewPacket when finished using it.\r
+\r
+ @param This The DHCP protocol instance.\r
+ @param SeedPacket The seed packet to start with\r
+ @param DeleteCount The number of options to delete\r
+ @param DeleteList The options to delete from the packet\r
+ @param AppendCount The number of options to append\r
+ @param AppendList The options to append to the packet\r
+ @param NewPacket The new packet, allocated and built by this\r
+ function.\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate memory\r
+ @retval EFI_SUCCESS The packet is build.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Build (\r
+ IN EFI_DHCP4_PROTOCOL *This,\r
+ IN EFI_DHCP4_PACKET *SeedPacket,\r
+ IN UINT32 DeleteCount,\r
+ IN UINT8 *DeleteList OPTIONAL,\r
+ IN UINT32 AppendCount,\r
+ IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,\r
+ OUT EFI_DHCP4_PACKET **NewPacket\r
+ )\r
+{\r
+ //\r
+ // First validate the parameters\r
+ //\r
+ if ((This == NULL) || (NewPacket == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
+ EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (((DeleteCount == 0) && (AppendCount == 0)) ||\r
+ ((DeleteCount != 0) && (DeleteList == NULL)) ||\r
+ ((AppendCount != 0) && (AppendList == NULL))) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ return DhcpBuild (\r
+ SeedPacket,\r
+ DeleteCount,\r
+ DeleteList,\r
+ AppendCount,\r
+ AppendList,\r
+ NewPacket\r
+ );\r
+}\r
+\r
+\r
+/**\r
+ Transmit and receive a packet through this DHCP service.\r
+ This is unsupported.\r
+\r
+ @param This The DHCP protocol instance\r
+ @param Token The transmit and receive instance\r
+\r
+ @retval EFI_UNSUPPORTED It always returns unsupported.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4TransmitReceive (\r
+ IN EFI_DHCP4_PROTOCOL *This,\r
+ IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token\r
+ )\r
+{\r
+ //\r
+ // This function is for PXE, leave it for now\r
+ //\r
+ return EFI_UNSUPPORTED;\r
+}\r
+\r
+\r
+/**\r
+ Callback function for DhcpIterateOptions. This callback sets the\r
+ EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point\r
+ the individual DHCP option in the packet.\r
+\r
+ @param Tag The DHCP option type\r
+ @param Len length of the DHCP option data\r
+ @param Data The DHCP option data\r
+ @param Context The context, to pass several parameters in.\r
+\r
+ @retval EFI_SUCCESS It always returns EFI_SUCCESS\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+Dhcp4ParseCheckOption (\r
+ IN UINT8 Tag,\r
+ IN UINT8 Len,\r
+ IN UINT8 *Data,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ DHCP_PARSE_CONTEXT *Parse;\r
+\r
+ Parse = (DHCP_PARSE_CONTEXT *) Context;\r
+ Parse->Index++;\r
+\r
+ if (Parse->Index < Parse->OptionCount) {\r
+ //\r
+ // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for\r
+ // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only\r
+ // pass in the point to option data.\r
+ //\r
+ Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Parse the DHCP options in the Packet into the PacketOptionList.\r
+ User should allocate this array of EFI_DHCP4_PACKET_OPTION points.\r
+\r
+ @param This The DHCP protocol instance\r
+ @param Packet The DHCP packet to parse\r
+ @param OptionCount On input, the size of the PacketOptionList; On\r
+ output, the actual number of options processed.\r
+ @param PacketOptionList The array of EFI_DHCP4_PACKET_OPTION points\r
+\r
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
+ @retval EFI_BUFFER_TOO_SMALL A bigger array of points is needed.\r
+ @retval EFI_SUCCESS The options are parsed.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+EFIAPI\r
+EfiDhcp4Parse (\r
+ IN EFI_DHCP4_PROTOCOL *This,\r
+ IN EFI_DHCP4_PACKET *Packet,\r
+ IN OUT UINT32 *OptionCount,\r
+ OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL\r
+ )\r
+{\r
+ DHCP_PARSE_CONTEXT Context;\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // First validate the parameters\r
+ //\r
+ if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||\r
+ (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
+ EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
+\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if ((*OptionCount != 0) && (PacketOptionList == NULL)) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
+\r
+ Context.Option = PacketOptionList;\r
+ Context.OptionCount = *OptionCount;\r
+ Context.Index = 0;\r
+\r
+ Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ *OptionCount = Context.Index;\r
+\r
+ if (Context.Index > Context.OptionCount) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {\r
+ EfiDhcp4GetModeData,\r
+ EfiDhcp4Configure,\r
+ EfiDhcp4Start,\r
+ EfiDhcp4RenewRebind,\r
+ EfiDhcp4Release,\r
+ EfiDhcp4Stop,\r
+ EfiDhcp4Build,\r
+ EfiDhcp4TransmitReceive,\r
+ EfiDhcp4Parse\r
+};\r
--- /dev/null
+/** @file
+
+Copyright (c) 2006, Intel Corporation
+All rights reserved. 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
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+ Dhcp4Impl.h
+
+Abstract:
+
+ EFI DHCP protocol implementation
+ RFCs supported are:
+ RFC 2131: Dynamic Host Configuration Protocol
+ RFC 2132: DHCP Options and BOOTP Vendor Extensions
+ RFC 1534: Interoperation Between DHCP and BOOTP
+ RFC 3396: Encoding Long Options in DHCP
+
+
+**/
+
+#ifndef __EFI_DHCP4_IMPL_H__
+#define __EFI_DHCP4_IMPL_H__
+
+
+\r
+#include <PiDxe.h>\r
+\r
+#include <Protocol/Dhcp4.h>\r
+#include <Protocol/Udp4.h>\r
+\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiDriverEntryPoint.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/BaseLib.h>
+#include <Library/NetLib.h>
+
+typedef struct _DHCP_SERVICE DHCP_SERVICE;
+typedef struct _DHCP_PROTOCOL DHCP_PROTOCOL;
+
+#include "Dhcp4Option.h"
+#include "Dhcp4Io.h"
+
+enum {
+ DHCP_SERVICE_SIGNATURE = EFI_SIGNATURE_32 ('D', 'H', 'C', 'P'),
+ DHCP_PROTOCOL_SIGNATURE = EFI_SIGNATURE_32 ('d', 'h', 'c', 'p'),
+
+ //
+ // The state of the DHCP service. It starts as UNCONFIGED. If
+ // and active child configures the service successfully, it
+ // goes to CONFIGED. If the active child configures NULL, it
+ // goes back to UNCONFIGED. It becomes DESTORY if it is (partly)
+ // destoried.
+ //
+ DHCP_UNCONFIGED = 0,
+ DHCP_CONFIGED,
+ DHCP_DESTORY,
+};
+
+typedef struct _DHCP_PROTOCOL {
+ UINT32 Signature;
+ EFI_DHCP4_PROTOCOL Dhcp4Protocol;
+ NET_LIST_ENTRY Link;
+ EFI_HANDLE Handle;
+ DHCP_SERVICE *Service;
+
+ BOOLEAN InDestory;
+
+ EFI_EVENT CompletionEvent;
+ EFI_EVENT RenewRebindEvent;
+
+ EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
+};
+
+//
+// DHCP driver is specical in that it is a singleton. Although it
+// has a service binding, there can be only one active child.
+//
+typedef struct _DHCP_SERVICE {
+ UINT32 Signature;
+ EFI_SERVICE_BINDING_PROTOCOL ServiceBinding;
+
+ INTN ServiceState; // CONFIGED, UNCONFIGED, and DESTORY
+ BOOLEAN InDestory;
+
+ EFI_HANDLE Controller;
+ EFI_HANDLE Image;
+
+ NET_LIST_ENTRY Children;
+ UINTN NumChildren;
+
+ INTN DhcpState;
+ EFI_STATUS IoStatus; // the result of last user operation
+ UINT32 Xid;
+
+ IP4_ADDR ClientAddr; // lease IP or configured client address
+ IP4_ADDR Netmask;
+ IP4_ADDR ServerAddr;
+
+ EFI_DHCP4_PACKET *LastOffer; // The last received offer
+ EFI_DHCP4_PACKET *Selected;
+ DHCP_PARAMETER *Para;
+
+ UINT32 Lease;
+ UINT32 T1;
+ UINT32 T2;
+ INTN ExtraRefresh; // This refresh is reqested by user
+
+ UDP_IO_PORT *UdpIo; // Udp child receiving all DHCP message
+ UDP_IO_PORT *LeaseIoPort; // Udp child with lease IP
+ NET_BUF *LastPacket; // The last sent packet for retransmission
+ EFI_MAC_ADDRESS Mac;
+ UINT8 HwType;
+ UINT8 HwLen;
+
+ DHCP_PROTOCOL *ActiveChild;
+ EFI_DHCP4_CONFIG_DATA ActiveConfig;
+ UINT32 UserOptionLen;
+
+ //
+ // Timer event and various timer
+ //
+ EFI_EVENT Timer;
+
+ UINT32 PacketToLive; // Retransmission timer for our packets
+ INTN CurRetry;
+ INTN MaxRetries;
+
+ UINT32 WaitOffer; // Time to collect the offers
+ UINT32 LeaseLife;
+};
+
+typedef struct {
+ EFI_DHCP4_PACKET_OPTION **Option;
+ UINT32 OptionCount;
+ UINT32 Index;
+} DHCP_PARSE_CONTEXT;
+
+#define DHCP_INSTANCE_FROM_THIS(Proto) \
+ CR ((Proto), DHCP_PROTOCOL, Dhcp4Protocol, DHCP_PROTOCOL_SIGNATURE)
+
+#define DHCP_SERVICE_FROM_THIS(Sb) \
+ CR ((Sb), DHCP_SERVICE, ServiceBinding, DHCP_SERVICE_SIGNATURE)
+
+extern EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate;
+
+VOID
+DhcpYieldControl (
+ IN DHCP_SERVICE *DhcpSb
+ );
+
+#endif
--- /dev/null
+/** @file\r
+\r
+Copyright (c) 2006 - 2007, Intel Corporation\r
+All rights reserved. This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+Module Name:\r
+\r
+ Dhcp4Io.c\r
+\r
+Abstract:\r
+\r
+ EFI DHCP protocol implementation\r
+\r
+\r
+**/\r
+\r
+\r
+#include "Dhcp4Impl.h"\r
+\r
+UINT32 mDhcp4DefaultTimeout[4] = { 4, 8, 16, 32 };\r
+\r
+\r
+/**\r
+ Send an initial DISCOVER or REQUEST message according to the\r
+ DHCP service's current state.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+\r
+ @retval EFI_SUCCESS The request has been sent\r
+\r
+**/\r
+EFI_STATUS\r
+DhcpInitRequest (\r
+ IN DHCP_SERVICE *DhcpSb\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT ((DhcpSb->DhcpState == Dhcp4Init) || (DhcpSb->DhcpState == Dhcp4InitReboot));\r
+\r
+ if (DhcpSb->DhcpState == Dhcp4Init) {\r
+ DhcpSetState (DhcpSb, Dhcp4Selecting, FALSE);\r
+ Status = DhcpSendMessage (DhcpSb, NULL, NULL, DHCP_MSG_DISCOVER, NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DhcpSb->DhcpState = Dhcp4Init;\r
+ return Status;\r
+ }\r
+\r
+ DhcpSb->WaitOffer = DHCP_WAIT_OFFER;\r
+ } else {\r
+ DhcpSetState (DhcpSb, Dhcp4Rebooting, FALSE);\r
+ Status = DhcpSendMessage (DhcpSb, NULL, NULL, DHCP_MSG_REQUEST, NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ DhcpSb->DhcpState = Dhcp4InitReboot;\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Call user provided callback function, and return the value the\r
+ function returns. If the user doesn't provide a callback, a\r
+ proper return value is selected to let the caller continue the\r
+ normal process.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+ @param Event The event as defined in the spec\r
+ @param Packet The current packet trigger the event\r
+ @param NewPacket The user's return new packet\r
+\r
+ @retval EFI_NOT_READY Direct the caller to continue collecting the offer.\r
+ @retval EFI_SUCCESS The user function returns success.\r
+ @retval EFI_ABORTED The user function ask it to abort.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+DhcpCallUser (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN EFI_DHCP4_EVENT Event,\r
+ IN EFI_DHCP4_PACKET *Packet, OPTIONAL\r
+ OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL\r
+ )\r
+{\r
+ EFI_DHCP4_CONFIG_DATA *Config;\r
+ EFI_STATUS Status;\r
+\r
+ if (NewPacket != NULL) {\r
+ *NewPacket = NULL;\r
+ }\r
+\r
+ //\r
+ // If user doesn't provide the call back function, return the value\r
+ // that directs the client to continue the normal process.\r
+ // In Dhcp4Selecting EFI_SUCCESS tells the client to stop collecting\r
+ // the offers and select a offer, EFI_NOT_READY tells the client to\r
+ // collect more offers.\r
+ //\r
+ Config = &DhcpSb->ActiveConfig;\r
+\r
+ if (Config->Dhcp4Callback == NULL) {\r
+ if (Event == Dhcp4RcvdOffer) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = Config->Dhcp4Callback (\r
+ &DhcpSb->ActiveChild->Dhcp4Protocol,\r
+ Config->CallbackContext,\r
+ DhcpSb->DhcpState,\r
+ Event,\r
+ Packet,\r
+ NewPacket\r
+ );\r
+\r
+ //\r
+ // User's callback should only return EFI_SUCCESS, EFI_NOT_READY,\r
+ // and EFI_ABORTED. If it returns values other than those, assume\r
+ // it to be EFI_ABORTED.\r
+ //\r
+ if ((Status == EFI_SUCCESS) || (Status == EFI_NOT_READY)) {\r
+ return Status;\r
+ }\r
+\r
+ return EFI_ABORTED;\r
+}\r
+\r
+\r
+/**\r
+ Notify the user about the operation result.\r
+\r
+ @param DhcpSb DHCP service instance\r
+ @param Which which notify function to signal\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+DhcpNotifyUser (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN INTN Which\r
+ )\r
+{\r
+ DHCP_PROTOCOL *Child;\r
+\r
+ if ((Child = DhcpSb->ActiveChild) == NULL) {\r
+ return ;\r
+ }\r
+\r
+ if ((Child->CompletionEvent != NULL) &&\r
+ ((Which == DHCP_NOTIFY_COMPLETION) || (Which == DHCP_NOTIFY_ALL))) {\r
+\r
+ gBS->SignalEvent (Child->CompletionEvent);\r
+ Child->CompletionEvent = NULL;\r
+ }\r
+\r
+ if ((Child->RenewRebindEvent != NULL) &&\r
+ ((Which == DHCP_NOTIFY_RENEWREBIND) || (Which == DHCP_NOTIFY_ALL))) {\r
+\r
+ gBS->SignalEvent (Child->RenewRebindEvent);\r
+ Child->RenewRebindEvent = NULL;\r
+ }\r
+}\r
+\r
+\r
+\r
+/**\r
+ Set the DHCP state. If CallUser is true, it will try to notify\r
+ the user before change the state by DhcpNotifyUser. It returns\r
+ EFI_ABORTED if the user return EFI_ABORTED, otherwise, it returns\r
+ EFI_SUCCESS. If CallUser is FALSE, it isn't necessary to test\r
+ the return value of this function.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+ @param State The new DHCP state to change to\r
+ @param CallUser Whether we need to call user\r
+\r
+ @retval EFI_SUCCESS The state is changed\r
+ @retval EFI_ABORTED The user asks to abort the DHCP process.\r
+\r
+**/\r
+EFI_STATUS\r
+DhcpSetState (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN INTN State,\r
+ IN BOOLEAN CallUser\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ if (CallUser) {\r
+ Status = EFI_SUCCESS;\r
+\r
+ if (State == Dhcp4Renewing) {\r
+ Status = DhcpCallUser (DhcpSb, Dhcp4EnterRenewing, NULL, NULL);\r
+\r
+ } else if (State == Dhcp4Rebinding) {\r
+ Status = DhcpCallUser (DhcpSb, Dhcp4EnterRebinding, NULL, NULL);\r
+\r
+ } else if (State == Dhcp4Bound) {\r
+ Status = DhcpCallUser (DhcpSb, Dhcp4BoundCompleted, NULL, NULL);\r
+\r
+ }\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Update the retransmission timer during the state transition.\r
+ // This will clear the retry count. This is also why the rule\r
+ // first transit the state, then send packets.\r
+ //\r
+ if (State == Dhcp4Init) {\r
+ DhcpSb->MaxRetries = DhcpSb->ActiveConfig.DiscoverTryCount;\r
+ } else {\r
+ DhcpSb->MaxRetries = DhcpSb->ActiveConfig.RequestTryCount;\r
+ }\r
+\r
+ if (DhcpSb->MaxRetries == 0) {\r
+ DhcpSb->MaxRetries = 4;\r
+ }\r
+\r
+ DhcpSb->CurRetry = 0;\r
+ DhcpSb->PacketToLive = 0;\r
+\r
+ DhcpSb->DhcpState = State;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Set the retransmit timer for the packet. It will select from either\r
+ the discover timeouts/request timeouts or the default timeout values.\r
+\r
+ @param DhcpSb The DHCP service instance.\r
+\r
+ @return None\r
+\r
+**/\r
+STATIC\r
+VOID\r
+DhcpSetTransmitTimer (\r
+ IN DHCP_SERVICE *DhcpSb\r
+ )\r
+{\r
+ UINT32 *Times;\r
+\r
+ ASSERT (DhcpSb->MaxRetries > DhcpSb->CurRetry);\r
+\r
+ if (DhcpSb->DhcpState == Dhcp4Init) {\r
+ Times = DhcpSb->ActiveConfig.DiscoverTimeout;\r
+ } else {\r
+ Times = DhcpSb->ActiveConfig.RequestTimeout;\r
+ }\r
+\r
+ if (Times == NULL) {\r
+ Times = mDhcp4DefaultTimeout;\r
+ }\r
+\r
+ DhcpSb->PacketToLive = Times[DhcpSb->CurRetry];\r
+}\r
+\r
+\r
+/**\r
+ Compute the lease. If the server grants a permanent lease, just\r
+ process it as a normal timeout value since the lease will last\r
+ more than 100 years.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+ @param Para The DHCP parameter extracted from the server's\r
+ response.\r
+\r
+ @return None\r
+\r
+**/\r
+STATIC\r
+VOID\r
+DhcpComputeLease (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN DHCP_PARAMETER *Para\r
+ )\r
+{\r
+ ASSERT (Para != NULL);\r
+\r
+ DhcpSb->Lease = Para->Lease;\r
+ DhcpSb->T2 = Para->T2;\r
+ DhcpSb->T1 = Para->T1;\r
+\r
+ if (DhcpSb->Lease == 0) {\r
+ DhcpSb->Lease = DHCP_DEFAULT_LEASE;\r
+ }\r
+\r
+ if ((DhcpSb->T2 == 0) || (DhcpSb->T2 >= Para->Lease)) {\r
+ DhcpSb->T2 = Para->Lease - (Para->Lease >> 3);\r
+ }\r
+\r
+ if ((DhcpSb->T1 == 0) || (DhcpSb->T1 >= Para->T2)) {\r
+ DhcpSb->T1 = DhcpSb->Lease >> 1;\r
+ }\r
+}\r
+\r
+\r
+/**\r
+ Configure a UDP IO port to use the acquired lease address.\r
+ DHCP driver needs this port to unicast packet to the server\r
+ such as DHCP release.\r
+\r
+ @param UdpIo The UDP IO port to configure\r
+ @param Context The opaque parameter to the function.\r
+\r
+ @retval EFI_SUCCESS The UDP IO port is successfully configured.\r
+ @retval Others It failed to configure the port.\r
+\r
+**/\r
+EFI_STATUS\r
+DhcpConfigLeaseIoPort (\r
+ IN UDP_IO_PORT *UdpIo,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ EFI_UDP4_CONFIG_DATA UdpConfigData;\r
+ EFI_IPv4_ADDRESS Subnet;\r
+ EFI_IPv4_ADDRESS Gateway;\r
+ DHCP_SERVICE *DhcpSb;\r
+ EFI_STATUS Status;\r
+ IP4_ADDR Ip;\r
+\r
+ DhcpSb = (DHCP_SERVICE *) Context;\r
+\r
+ UdpConfigData.AcceptBroadcast = FALSE;\r
+ UdpConfigData.AcceptPromiscuous = FALSE;\r
+ UdpConfigData.AcceptAnyPort = FALSE;\r
+ UdpConfigData.AllowDuplicatePort = TRUE;\r
+ UdpConfigData.TypeOfService = 0;\r
+ UdpConfigData.TimeToLive = 64;\r
+ UdpConfigData.DoNotFragment = FALSE;\r
+ UdpConfigData.ReceiveTimeout = 1;\r
+ UdpConfigData.TransmitTimeout = 0;\r
+\r
+ UdpConfigData.UseDefaultAddress = FALSE;\r
+ UdpConfigData.StationPort = DHCP_CLIENT_PORT;\r
+ UdpConfigData.RemotePort = DHCP_SERVER_PORT;\r
+\r
+ Ip = HTONL (DhcpSb->ClientAddr);\r
+ NetCopyMem (&UdpConfigData.StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ Ip = HTONL (DhcpSb->Netmask);\r
+ NetCopyMem (&UdpConfigData.SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ NetZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Add a default route if received from the server.\r
+ //\r
+ if ((DhcpSb->Para != NULL) && (DhcpSb->Para->Router != 0)) {\r
+ NetZeroMem (&Subnet, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ Ip = HTONL (DhcpSb->Para->Router);\r
+ NetCopyMem (&Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+ UdpIo->Udp->Routes (UdpIo->Udp, FALSE, &Subnet, &Subnet, &Gateway);\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+ Update the lease states when a new lease is acquired. It will not only\r
+ save the acquired the address and lease time, it will also create a UDP\r
+ child to provide address resolution for the address.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.\r
+ @retval EFI_SUCCESS The lease is recorded.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+DhcpLeaseAcquired (\r
+ IN DHCP_SERVICE *DhcpSb\r
+ )\r
+{\r
+ INTN Class;\r
+\r
+ DhcpSb->ClientAddr = EFI_NTOHL (DhcpSb->Selected->Dhcp4.Header.YourAddr);\r
+\r
+ if (DhcpSb->Para != NULL) {\r
+ DhcpSb->Netmask = DhcpSb->Para->NetMask;\r
+ DhcpSb->ServerAddr = DhcpSb->Para->ServerId;\r
+ }\r
+\r
+ if (DhcpSb->Netmask == 0) {\r
+ Class = NetGetIpClass (DhcpSb->ClientAddr);\r
+ DhcpSb->Netmask = mIp4AllMasks[Class << 3];\r
+ }\r
+\r
+ if (DhcpSb->LeaseIoPort != NULL) {\r
+ UdpIoFreePort (DhcpSb->LeaseIoPort);\r
+ }\r
+\r
+ //\r
+ // Create a UDP/IP child to provide ARP service for the Leased IP,\r
+ // and transmit unicast packet with it as source address. Don't\r
+ // start receive on this port, the queued packet will be timeout.\r
+ //\r
+ DhcpSb->LeaseIoPort = UdpIoCreatePort (\r
+ DhcpSb->Controller,\r
+ DhcpSb->Image,\r
+ DhcpConfigLeaseIoPort,\r
+ DhcpSb\r
+ );\r
+\r
+ if (DhcpSb->LeaseIoPort == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (!DHCP_IS_BOOTP (DhcpSb->Para)) {\r
+ DhcpComputeLease (DhcpSb, DhcpSb->Para);\r
+ }\r
+\r
+ return DhcpSetState (DhcpSb, Dhcp4Bound, TRUE);\r
+}\r
+\r
+\r
+/**\r
+ Clean up the DHCP related states, IoStatus isn't reset.\r
+\r
+ @param DhcpSb The DHCP instance service.\r
+\r
+ @return None\r
+\r
+**/\r
+VOID\r
+DhcpCleanLease (\r
+ IN DHCP_SERVICE *DhcpSb\r
+ )\r
+{\r
+ DhcpSb->DhcpState = Dhcp4Init;\r
+ DhcpSb->Xid = DhcpSb->Xid + 1;\r
+ DhcpSb->ClientAddr = 0;\r
+ DhcpSb->ServerAddr = 0;\r
+\r
+ if (DhcpSb->LastOffer != NULL) {\r
+ NetFreePool (DhcpSb->LastOffer);\r
+ DhcpSb->LastOffer = NULL;\r
+ }\r
+\r
+ if (DhcpSb->Selected != NULL) {\r
+ NetFreePool (DhcpSb->Selected);\r
+ DhcpSb->Selected = NULL;\r
+ }\r
+\r
+ if (DhcpSb->Para != NULL) {\r
+ NetFreePool (DhcpSb->Para);\r
+ DhcpSb->Para = NULL;\r
+ }\r
+\r
+ DhcpSb->Lease = 0;\r
+ DhcpSb->T1 = 0;\r
+ DhcpSb->T2 = 0;\r
+ DhcpSb->ExtraRefresh = FALSE;\r
+\r
+ if (DhcpSb->LeaseIoPort != NULL) {\r
+ UdpIoFreePort (DhcpSb->LeaseIoPort);\r
+ DhcpSb->LeaseIoPort = NULL;\r
+ }\r
+\r
+ if (DhcpSb->LastPacket != NULL) {\r
+ NetbufFree (DhcpSb->LastPacket);\r
+ DhcpSb->LastPacket = NULL;\r
+ }\r
+\r
+ DhcpSb->PacketToLive = 0;\r
+ DhcpSb->CurRetry = 0;\r
+ DhcpSb->MaxRetries = 0;\r
+ DhcpSb->WaitOffer = 0;\r
+ DhcpSb->LeaseLife = 0;\r
+}\r
+\r
+\r
+/**\r
+ Select a offer among all the offers collected. If the offer selected is\r
+ of BOOTP, the lease is recorded and user notified. If the offer is of\r
+ DHCP, it will request the offer from the server.\r
+\r
+ @param DhcpSb The DHCP service instance.\r
+\r
+ @retval EFI_SUCCESS One of the offer is selected.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+DhcpChooseOffer (\r
+ IN DHCP_SERVICE *DhcpSb\r
+ )\r
+{\r
+ EFI_DHCP4_PACKET *Selected;\r
+ EFI_DHCP4_PACKET *NewPacket;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (DhcpSb->LastOffer != NULL);\r
+\r
+ //\r
+ // Stop waiting more offers\r
+ //\r
+ DhcpSb->WaitOffer = 0;\r
+\r
+ //\r
+ // User will cache previous offers if he wants to select\r
+ // from multiple offers. If user provides an invalid packet,\r
+ // use the last offer, otherwise use the provided packet.\r
+ //\r
+ NewPacket = NULL;\r
+ Status = DhcpCallUser (DhcpSb, Dhcp4SelectOffer, DhcpSb->LastOffer, &NewPacket);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Selected = DhcpSb->LastOffer;\r
+\r
+ if (NewPacket != NULL) {\r
+ if (EFI_ERROR (DhcpValidateOptions (NewPacket, NULL))) {\r
+ NetFreePool (NewPacket);\r
+ } else {\r
+ NetFreePool (Selected);\r
+ Selected = NewPacket;\r
+ }\r
+ }\r
+\r
+ DhcpSb->Selected = Selected;\r
+ DhcpSb->LastOffer = NULL;\r
+ DhcpSb->Para = NULL;\r
+ DhcpValidateOptions (Selected, &DhcpSb->Para);\r
+\r
+ //\r
+ // A bootp offer has been selected, save the lease status,\r
+ // enter bound state then notify the user.\r
+ //\r
+ if (DHCP_IS_BOOTP (DhcpSb->Para)) {\r
+ Status = DhcpLeaseAcquired (DhcpSb);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ DhcpSb->IoStatus = EFI_SUCCESS;\r
+ DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_ALL);\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Send a DHCP requests\r
+ //\r
+ Status = DhcpSetState (DhcpSb, Dhcp4Requesting, TRUE);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return DhcpSendMessage (DhcpSb, Selected, DhcpSb->Para, DHCP_MSG_REQUEST, NULL);\r
+}\r
+\r
+\r
+/**\r
+ Terminate the current address acquire. All the allocated resources\r
+ are released. Be careful when calling this function. A rule related\r
+ to this is: only call DhcpEndSession at the highest level, such as\r
+ DhcpInput, DhcpOnTimerTick...At the other level, just return error.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+ @param Status The result of the DHCP process.\r
+\r
+ @return None\r
+\r
+**/\r
+STATIC\r
+VOID\r
+DhcpEndSession (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN EFI_STATUS Status\r
+ )\r
+{\r
+ if (DHCP_CONNECTED (DhcpSb->DhcpState)) {\r
+ DhcpCallUser (DhcpSb, Dhcp4AddressLost, NULL, NULL);\r
+ } else {\r
+ DhcpCallUser (DhcpSb, Dhcp4Fail, NULL, NULL);\r
+ }\r
+\r
+ DhcpCleanLease (DhcpSb);\r
+\r
+ DhcpSb->IoStatus = Status;\r
+ DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_ALL);\r
+}\r
+\r
+\r
+/**\r
+ Handle packets in DHCP select state.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+ @param Packet The DHCP packet received\r
+ @param Para The DHCP parameter extracted from the packet. That\r
+ is, all the option value that we care.\r
+\r
+ @retval EFI_SUCCESS The packet is successfully processed.\r
+ @retval Others Some error occured.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+DhcpHandleSelect (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN EFI_DHCP4_PACKET *Packet,\r
+ IN DHCP_PARAMETER *Para\r
+ )\r
+{\r
+ EFI_DHCP4_HEADER *Head;\r
+ EFI_STATUS Status;\r
+\r
+ Status = EFI_SUCCESS;\r
+\r
+ //\r
+ // First validate the message:\r
+ // 1. the offer is a unicast\r
+ // 2. if it is a DHCP message, it must contains a server ID.\r
+ // Don't return a error for these two case otherwise the session is ended.\r
+ //\r
+ Head = &Packet->Dhcp4.Header;\r
+\r
+ if (!Ip4IsUnicast (EFI_NTOHL (Head->YourAddr), (Para == NULL ? 0 : Para->NetMask))) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ if (!DHCP_IS_BOOTP (Para) &&\r
+ ((Para->DhcpType != DHCP_MSG_OFFER) || (Para->ServerId == 0))) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Call the user's callback. The action according to the return is as:\r
+ // 1. EFI_SUCESS: stop waiting for more offers, select the offer now\r
+ // 2. EFI_NOT_READY: wait for more offers\r
+ // 3. EFI_ABORTED: abort the address acquiring.\r
+ //\r
+ Status = DhcpCallUser (DhcpSb, Dhcp4RcvdOffer, Packet, NULL);\r
+\r
+ if (Status == EFI_SUCCESS) {\r
+ if (DhcpSb->LastOffer != NULL) {\r
+ NetFreePool (DhcpSb->LastOffer);\r
+ }\r
+\r
+ DhcpSb->LastOffer = Packet;\r
+\r
+ return DhcpChooseOffer (DhcpSb);\r
+\r
+ } else if (Status == EFI_NOT_READY) {\r
+ if (DhcpSb->LastOffer != NULL) {\r
+ NetFreePool (DhcpSb->LastOffer);\r
+ }\r
+\r
+ DhcpSb->LastOffer = Packet;\r
+\r
+ } else if (Status == EFI_ABORTED) {\r
+ //\r
+ // DhcpInput will end the session upon error return. Remember\r
+ // only to call DhcpEndSession at the top level call.\r
+ //\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+\r
+ON_EXIT:\r
+ NetFreePool (Packet);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Handle packets in DHCP request state.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+ @param Packet The DHCP packet received\r
+ @param Para The DHCP parameter extracted from the packet. That\r
+ is, all the option value that we care.\r
+\r
+ @retval EFI_SUCCESS The packet is successfully processed.\r
+ @retval Others Some error occured.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+DhcpHandleRequest (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN EFI_DHCP4_PACKET *Packet,\r
+ IN DHCP_PARAMETER *Para\r
+ )\r
+{\r
+ EFI_DHCP4_HEADER *Head;\r
+ EFI_DHCP4_HEADER *Selected;\r
+ EFI_STATUS Status;\r
+ UINT8 *Message;\r
+\r
+ ASSERT (!DHCP_IS_BOOTP (DhcpSb->Para));\r
+\r
+ Head = &Packet->Dhcp4.Header;\r
+ Selected = &DhcpSb->Selected->Dhcp4.Header;\r
+\r
+ //\r
+ // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK.\r
+ //\r
+ if (DHCP_IS_BOOTP (Para) ||\r
+ (Para->ServerId != DhcpSb->Para->ServerId) ||\r
+ ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) {\r
+\r
+ Status = EFI_SUCCESS;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Received a NAK, end the session no matter what the user returns\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ if (Para->DhcpType == DHCP_MSG_NAK) {\r
+ DhcpCallUser (DhcpSb, Dhcp4RcvdNak, Packet, NULL);\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Check whether the ACK matches the selected offer\r
+ //\r
+ Message = NULL;\r
+\r
+ if (!EFI_IP4_EQUAL (Head->YourAddr, Selected->YourAddr)) {\r
+ Message = "Lease confirmed isn't the same as that in the offer";\r
+ goto REJECT;\r
+ }\r
+\r
+ Status = DhcpCallUser (DhcpSb, Dhcp4RcvdAck, Packet, NULL);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Message = "Lease is denied upon received ACK";\r
+ goto REJECT;\r
+ }\r
+\r
+ //\r
+ // Record the lease, transit to BOUND state, then notify the user\r
+ //\r
+ Status = DhcpLeaseAcquired (DhcpSb);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ Message = "Lease is denied upon entering bound";\r
+ goto REJECT;\r
+ }\r
+\r
+ DhcpSb->IoStatus = EFI_SUCCESS;\r
+ DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_COMPLETION);\r
+\r
+ NetFreePool (Packet);\r
+ return EFI_SUCCESS;\r
+\r
+REJECT:\r
+ DhcpSendMessage (DhcpSb, DhcpSb->Selected, DhcpSb->Para, DHCP_MSG_DECLINE, Message);\r
+\r
+ON_EXIT:\r
+ NetFreePool (Packet);\r
+ return Status;\r
+}\r
+\r
+\r
+/**\r
+ Handle packets in DHCP renew/rebound state.\r
+\r
+ @param DhcpSb The DHCP service instance\r
+ @param Packet The DHCP packet received\r
+ @param Para The DHCP parameter extracted from the packet. That\r
+ is, all the option value that we care.\r
+\r
+ @retval EFI_SUCCESS The packet is successfully processed.\r
+ @retval Others Some error occured.\r
+\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+DhcpHandleRenewRebind (\r
+ IN DHCP_SERVICE *DhcpSb,\r
+ IN EFI_DHCP4_PACKET *Packet,\r
+ IN DHCP_PARAMETER *Para\r
+ )\r
+{\r
+ EFI_DHCP4_HEADER *Head;\r
+ EFI_DHCP4_HEADER *Selected;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (!DHCP_IS_BOOTP (DhcpSb->Para));\r
+\r
+ Head = &Packet->Dhcp4.Header;\r
+ Selected = &DhcpSb->Selected->Dhcp4.Header;\r
+\r
+ //\r
+ // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK\r
+ //\r
+ if (DHCP_IS_BOOTP (Para) ||\r
+ (Para->ServerId != DhcpSb->Para->ServerId) ||\r
+ ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) {\r
+\r
+ Status = EFI_SUCCESS;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Received a NAK, ignore the user's return then terminate the process\r
+ //\r
+ Status = EFI_DEVICE_ERROR;\r
+\r
+ if (Para->DhcpType == DHCP_MSG_NAK) {\r
+ DhcpCallUser (DhcpSb, Dhcp4RcvdNak, Packet, NULL);\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // The lease is different from the selected. Don't send a DECLINE\r
+ // since it isn't existed in the client's FSM.\r
+ //\r
+ if (!EFI_IP4_EQUAL (Head->YourAddr, Selected->YourAddr)) {\r
+ goto ON_EXIT;\r