]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_dhcp.c
1. Import UEFI PxeBc module in MdeModulePkg
[mirror_edk2.git] / MdeModulePkg / Universal / Network / PxeBcDxe / Pxe_bc_dhcp.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2004 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13 pxe_bc_dhcp.c\r
14\r
15Abstract:\r
16 DHCP and PXE discovery protocol implementations.\r
17\r
18\r
19**/\r
20\r
21#include "Bc.h"\r
22\r
23#include "PxeArch.h"\r
24\r
25STATIC EFI_PXE_BASE_CODE_UDP_PORT DhcpServerPort = DHCP_SERVER_PORT;\r
26STATIC EFI_PXE_BASE_CODE_UDP_PORT DHCPClientPort = DHCP_CLIENT_PORT;\r
27STATIC EFI_PXE_BASE_CODE_UDP_PORT PseudoDhcpServerPort = PXE_DISCOVERY_PORT;\r
28#define PSEUDO_DHCP_CLIENT_PORT PseudoDhcpServerPort\r
84b5c78e 29STATIC EFI_IP_ADDRESS BroadcastIP = {{0xffffffff}};\r
30STATIC EFI_IP_ADDRESS DefaultSubnetMask = {{0xffffff00}};\r
772db4bb 31\r
32typedef union {\r
33 DHCPV4_OP_STRUCT *OpPtr;\r
34 PXE_OP_SERVER_LIST *BootServersStr;\r
35 PXE_SERVER_LIST *BootServerList;\r
36 PXE_BOOT_MENU_ENTRY *BootMenuItem;\r
37 PXE_OP_DISCOVERY_CONTROL *DiscoveryControl;\r
38 PXE_OP_BOOT_MENU *BootMenu;\r
39 PXE_OP_BOOT_ITEM *BootItem;\r
40 DHCPV4_OP_VENDOR_OPTIONS *VendorOptions;\r
41 DHCPV4_OP_OVERLOAD *Overload;\r
42 DHCPV4_OP_CLASS *PxeClassStr;\r
43 DHCPV4_OP_SUBNET_MASK *SubnetMaskStr;\r
44 DHCPV4_OP_MESSAGE_TYPE *MessageType;\r
45 UINT8 *BytePtr;\r
46} UNION_PTR;\r
47\r
48#pragma pack(1)\r
49//\r
50// option structure for DHCPREQUEST at end of DISCOVER options\r
51// and for DHCPDECLINE\r
52//\r
53STATIC const struct requestopendstr {\r
54 DHCPV4_OP_REQUESTED_IP OpReqIP;\r
55 DHCPV4_OP_SERVER_IP DhcServerIpPtr;\r
56 UINT8 End[1];\r
57}\r
58RequestOpEndStr = {\r
59 {\r
60 {\r
61 OP_DHCP_REQ_IP_ADD,\r
62 DHCPV4_OPTION_LENGTH(DHCPV4_OP_REQUESTED_IP)\r
63 }\r
64 },\r
65 {\r
66 {\r
67 OP_DHCP_SERVER_IP,\r
68 DHCPV4_OPTION_LENGTH(DHCPV4_OP_SERVER_IP)\r
69 }\r
70 },\r
71 {\r
72 OP_END\r
73 }\r
74};\r
75\r
76#define DHCP_REQ_OPTIONS (*(struct requestopendstr *) DHCPV4_OPTIONS_BUFFER.End)\r
77\r
78PXE_OP_BOOT_ITEM DefaultBootItem = {\r
79 {\r
80 VEND_PXE_BOOT_ITEM,\r
81 DHCPV4_OPTION_LENGTH(PXE_OP_BOOT_ITEM)\r
82 },\r
83 0,\r
84 0\r
85};\r
86\r
87//\r
88// PXE discovery control default structure\r
89//\r
90STATIC PXE_OP_DISCOVERY_CONTROL DefaultDisCtl = {\r
91 { VEND_PXE_DISCOVERY_CONTROL, DHCPV4_OPTION_LENGTH(PXE_OP_DISCOVERY_CONTROL) },\r
92 0\r
93};\r
94\r
95//\r
96// PXE credentials option structure\r
97//\r
98typedef struct {\r
99 UINT8 c[4];\r
100} PXE_CREDENTIAL;\r
101\r
102typedef struct {\r
103 DHCPV4_OP_HEADER Header;\r
104 PXE_CREDENTIAL Credentials[1];\r
105} PXE_OP_CREDENTIAL_TYPES;\r
106\r
107//\r
108// option structure for PXE discover (without credentials)\r
109//\r
110typedef struct { // discoveropendstr {\r
111 DHCPV4_OP_HEADER Header; // vendor options\r
112 PXE_OP_BOOT_ITEM BootItem;\r
113 UINT8 End[1]; // if credentials option, it starts here\r
114} PXE_DISCOVER_OPTIONS;\r
115\r
116#define DISCOVERoptions (*(PXE_DISCOVER_OPTIONS *) DHCPV4_OPTIONS_BUFFER.End)\r
117#define DISCREDoptions (*(PXE_OP_CREDENTIAL_TYPES *) DISCOVERoptions.End)\r
118\r
119//\r
120// common option beginning for all our DHCP messages except\r
121// DHCPDECLINE and DHCPRELEASE\r
122//\r
123STATIC struct optionsstr {\r
124 UINT8 DhcpCookie[4];\r
125 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType;\r
126 DHCPV4_OP_MAX_MESSAGE_SIZE DhcpMaxMessageSize;\r
127 DHCPV4_OP_REQUESTED_OPTIONS DhcpRequestedOptions;\r
128 DHCPV4_OP_PLATFORM_ID DhcpPlatformId;\r
129 DHCPV4_OP_NETWORK_INTERFACE DhcpNetworkInterface;\r
130 DHCPV4_OP_ARCHITECTURE_TYPE DhcpClientArchitecture;\r
131 DHCPV4_OP_CLASS_ID DhcpClassIdentifier;\r
132 UINT8 End[1];\r
133} DHCPOpStart;\r
134\r
135/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
136VOID\r
137OptionsStrucInit (\r
138 VOID\r
139 )\r
140{\r
141 DHCPOpStart.DhcpCookie[0] = 99;\r
142 DHCPOpStart.DhcpCookie[1] = 130;\r
143 DHCPOpStart.DhcpCookie[2] = 83;\r
144 DHCPOpStart.DhcpCookie[3] = 99;\r
145 DHCPOpStart.DhcpMessageType.Header.OpCode = OP_DHCP_MESSAGE_TYPE;\r
146 DHCPOpStart.DhcpMessageType.Header.Length = 1;\r
147 DHCPOpStart.DhcpMessageType.Type = DHCPDISCOVER;\r
148 DHCPOpStart.DhcpMaxMessageSize.Header.OpCode = OP_DHCP_MAX_MESSAGE_SZ;\r
149 DHCPOpStart.DhcpMaxMessageSize.Header.Length = 2;\r
150 DHCPOpStart.DhcpMaxMessageSize.MaxSize[0] = MAX_DHCP_MSG_SZ >> 8;\r
151 DHCPOpStart.DhcpMaxMessageSize.MaxSize[1] = MAX_DHCP_MSG_SZ & 0xff;\r
152 DHCPOpStart.DhcpRequestedOptions.Header.OpCode = OP_DHCP_PARM_REQ_LIST;\r
153 DHCPOpStart.DhcpRequestedOptions.Header.Length = sizeof (DHCPV4_REQUESTED_OPTIONS_DATA);\r
154 DHCPOpStart.DhcpRequestedOptions.Data._OP_SUBNET_MASK = OP_SUBNET_MASK; /* 1 */\r
155 DHCPOpStart.DhcpRequestedOptions.Data._OP_TIME_OFFSET = OP_TIME_OFFSET; /* 2 */\r
156 DHCPOpStart.DhcpRequestedOptions.Data._OP_ROUTER_LIST = OP_ROUTER_LIST; /* 3 */\r
157 DHCPOpStart.DhcpRequestedOptions.Data._OP_TIME_SERVERS = OP_TIME_SERVERS; /* 4 */\r
158 DHCPOpStart.DhcpRequestedOptions.Data._OP_NAME_SERVERS = OP_NAME_SERVERS; /* 5 */\r
159 DHCPOpStart.DhcpRequestedOptions.Data._OP_DNS_SERVERS = OP_DNS_SERVERS; /* 6 */\r
160 DHCPOpStart.DhcpRequestedOptions.Data._OP_HOST_NAME = OP_HOST_NAME; /* 12 */\r
161 DHCPOpStart.DhcpRequestedOptions.Data._OP_BOOT_FILE_SZ = OP_BOOT_FILE_SZ; /* 13 */\r
162 DHCPOpStart.DhcpRequestedOptions.Data._OP_DOMAIN_NAME = OP_DOMAIN_NAME; /* 15 */\r
163 DHCPOpStart.DhcpRequestedOptions.Data._OP_ROOT_PATH = OP_ROOT_PATH; /* 17 */\r
164 DHCPOpStart.DhcpRequestedOptions.Data._OP_EXTENSION_PATH = OP_EXTENSION_PATH; /* 18 */\r
165 DHCPOpStart.DhcpRequestedOptions.Data._OP_MAX_DATAGRAM_SZ = OP_MAX_DATAGRAM_SZ; /* 22 */\r
166 DHCPOpStart.DhcpRequestedOptions.Data._OP_DEFAULT_TTL = OP_DEFAULT_TTL; /* 23 */\r
167 DHCPOpStart.DhcpRequestedOptions.Data._OP_BROADCAST_ADD = OP_BROADCAST_ADD; /* 28 */\r
168 DHCPOpStart.DhcpRequestedOptions.Data._OP_NIS_DOMAIN_NAME = OP_NIS_DOMAIN_NAME; /* 40 */\r
169 DHCPOpStart.DhcpRequestedOptions.Data._OP_NIS_SERVERS = OP_NIS_SERVERS; /* 41 */\r
170 DHCPOpStart.DhcpRequestedOptions.Data._OP_NTP_SERVERS = OP_NTP_SERVERS; /* 42 */\r
171 DHCPOpStart.DhcpRequestedOptions.Data._OP_VENDOR_SPECIFIC = OP_VENDOR_SPECIFIC; /* 43 */\r
172 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_REQ_IP_ADD = OP_DHCP_REQ_IP_ADD; /* 50 */\r
173 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_LEASE_TIME = OP_DHCP_LEASE_TIME; /* 51 */\r
174 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_SERVER_IP = OP_DHCP_SERVER_IP; /* 54 */\r
175 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_RENEWAL_TIME = OP_DHCP_RENEWAL_TIME; /* 58 */\r
176 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_REBINDING_TIME = OP_DHCP_REBINDING_TIME; /* 59 */\r
177 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_CLASS_IDENTIFIER = OP_DHCP_CLASS_IDENTIFIER; /* 60 */\r
178 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_TFTP_SERVER_NAME = OP_DHCP_TFTP_SERVER_NAME; /* 66 */\r
179 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_BOOTFILE = OP_DHCP_BOOTFILE; /* 67 */\r
180 DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_PLATFORM_ID = OP_DHCP_PLATFORM_ID; /* 97 */\r
181 DHCPOpStart.DhcpRequestedOptions.Data.VendorOption128 = 128;\r
182 DHCPOpStart.DhcpRequestedOptions.Data.VendorOption129 = 129;\r
183 DHCPOpStart.DhcpRequestedOptions.Data.VendorOption130 = 130;\r
184 DHCPOpStart.DhcpRequestedOptions.Data.VendorOption131 = 131;\r
185 DHCPOpStart.DhcpRequestedOptions.Data.VendorOption132 = 132;\r
186 DHCPOpStart.DhcpRequestedOptions.Data.VendorOption133 = 133, DHCPOpStart.DhcpRequestedOptions.Data.VendorOption134 = 134;\r
187 DHCPOpStart.DhcpRequestedOptions.Data.VendorOption135 = 135;\r
188 DHCPOpStart.DhcpPlatformId.Header.OpCode = OP_DHCP_PLATFORM_ID;\r
189 DHCPOpStart.DhcpPlatformId.Header.Length = DHCPV4_OPTION_LENGTH (DHCPV4_OP_PLATFORM_ID);\r
190 DHCPOpStart.DhcpNetworkInterface.Header.OpCode = OP_DHCP_NETWORK_ARCH;\r
191 DHCPOpStart.DhcpNetworkInterface.Header.Length = DHCPV4_OPTION_LENGTH (DHCPV4_OP_NETWORK_INTERFACE);\r
192 DHCPOpStart.DhcpNetworkInterface.Type = 0;\r
193 DHCPOpStart.DhcpNetworkInterface.MajorVersion = 0;\r
194 DHCPOpStart.DhcpNetworkInterface.MinorVersion = 0;\r
195 DHCPOpStart.DhcpClientArchitecture.Header.OpCode = OP_DHCP_SYSTEM_ARCH;\r
196 DHCPOpStart.DhcpClientArchitecture.Header.Length = DHCPV4_OPTION_LENGTH (DHCPV4_OP_ARCHITECTURE_TYPE);\r
197 DHCPOpStart.DhcpClientArchitecture.Type = HTONS (SYS_ARCH);\r
198 DHCPOpStart.DhcpClassIdentifier.Header.OpCode = OP_DHCP_CLASS_IDENTIFIER;\r
199 DHCPOpStart.DhcpClassIdentifier.Header.Length = sizeof (DHCPV4_CLASS_ID_DATA);\r
200 CopyMem (\r
201 DHCPOpStart.DhcpClassIdentifier.Data.ClassIdentifier,\r
202 "PXEClient:",\r
203 sizeof ("PXEClient:")\r
204 );\r
205 CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.Lit2, "Arch:", sizeof ("Arch:"));\r
206 CopyMem (\r
207 DHCPOpStart.DhcpClassIdentifier.Data.ArchitectureType,\r
208 "xxxxx",\r
209 sizeof ("xxxxx")\r
210 );\r
211 CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.Lit3, ":", sizeof (":"));\r
212 CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.InterfaceName, "XXXX", sizeof ("XXXX"));\r
213 CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.Lit4, ":", sizeof (":"));\r
214 CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.UndiMajor, "yyy", sizeof ("yyy"));\r
215 CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.UndiMinor, "xxx", sizeof ("xxx"));\r
216 DHCPOpStart.End[0] = OP_END;\r
687a2e5f 217}\r
772db4bb 218\r
219/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
220\r
221//\r
222// DHCPDECLINE option structure\r
223//\r
224struct opdeclinestr {\r
225 UINT8 DhcpCookie[4];\r
226 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType;\r
227 struct requestopendstr OpDeclineEnd;\r
228};\r
229\r
230#define DHCPDECLINEoptions (*(struct opdeclinestr *) DHCPV4_TRANSMIT_BUFFER.options)\r
231\r
232//\r
233// DHCPRELEASE option structure\r
234//\r
235struct opreleasestr {\r
236 UINT8 DhcpCookie[4];\r
237 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType;\r
238 DHCPV4_OP_SERVER_IP DhcServerIpPtr;\r
239 UINT8 End[1];\r
240};\r
241\r
242#define DHCPRELEASEoptions (*(struct opreleasestr *) DHCPV4_TRANSMIT_BUFFER.options)\r
243\r
244//\r
245// array of PXE vendor options in which we are interested\r
246// value 0 -> not of interest, else value is index into PXE OPTION array\r
247// option values from 1 to MAX_OUR_PXE_OPT\r
248//\r
249STATIC UINT8 ourPXEopts[MAX_OUR_PXE_OPT] = {\r
250 VEND_PXE_MTFTP_IP_IX, // multicast IP address of bootfile for MTFTP listen\r
251 VEND_PXE_MTFTP_CPORT_IX, // UDP Port to monitor for MTFTP responses - Intel order\r
252 VEND_PXE_MTFTP_SPORT_IX, // Server UDP Port for MTFTP open - Intel order\r
253 VEND_PXE_MTFTP_TMOUT_IX, // Listen timeout - secs\r
254 VEND_PXE_MTFTP_DELAY_IX, // Transmission timeout - secs\r
255 VEND_PXE_DISCOVERY_CONTROL_IX, // bit field\r
256 VEND_PXE_DISCOVERY_MCAST_ADDR_IX, // boot server discovery multicast address\r
257 VEND_PXE_BOOT_SERVERS_IX, // list of boot servers of form tp(2) cnt(1) ips[cnt]\r
258 VEND_PXE_BOOT_MENU_IX,\r
259 VEND_PXE_BOOT_PROMPT_IX,\r
260 VEND_PXE_MCAST_ADDRS_ALLOC_IX, // not used by client\r
261 VEND_PXE_CREDENTIAL_TYPES_IX,\r
262 VEND_13_IX, // not used by client\r
263 VEND_14_IX, // not used by client\r
264 VEND_15_IX, // not used by client\r
265 VEND_16_IX, // not used by client\r
266 VEND_17_IX, // not used by client\r
267 VEND_18_IX, // not used by client\r
268 VEND_19_IX, // not used by client\r
269 VEND_20_IX, // not used by client\r
270 VEND_21_IX, // not used by client\r
271 VEND_22_IX, // not used by client\r
272 VEND_23_IX, // not used by client\r
273 VEND_24_IX, // not used by client\r
274 VEND_25_IX, // not used by client\r
275 VEND_26_IX, // not used by client\r
276 VEND_27_IX, // not used by client\r
277 VEND_28_IX, // not used by client\r
278 VEND_29_IX, // not used by client\r
279 VEND_30_IX, // not used by client\r
280 VEND_31_IX, // not used by client\r
281 VEND_32_IX, // not used by client\r
282 VEND_33_IX, // not used by client\r
283 VEND_34_IX, // not used by client\r
284 VEND_35_IX, // not used by client\r
285 VEND_36_IX, // not used by client\r
286 VEND_37_IX, // not used by client\r
287 VEND_38_IX, // not used by client\r
288 VEND_39_IX, // not used by client\r
289 VEND_40_IX, // not used by client\r
290 VEND_41_IX, // not used by client\r
291 VEND_42_IX, // not used by client\r
292 VEND_43_IX, // not used by client\r
293 VEND_44_IX, // not used by client\r
294 VEND_45_IX, // not used by client\r
295 VEND_46_IX, // not used by client\r
296 VEND_47_IX, // not used by client\r
297 VEND_48_IX, // not used by client\r
298 VEND_49_IX, // not used by client\r
299 VEND_50_IX, // not used by client\r
300 VEND_51_IX, // not used by client\r
301 VEND_52_IX, // not used by client\r
302 VEND_53_IX, // not used by client\r
303 VEND_54_IX, // not used by client\r
304 VEND_55_IX, // not used by client\r
305 VEND_56_IX, // not used by client\r
306 VEND_57_IX, // not used by client\r
307 VEND_58_IX, // not used by client\r
308 VEND_59_IX, // not used by client\r
309 VEND_60_IX, // not used by client\r
310 VEND_61_IX, // not used by client\r
311 VEND_62_IX, // not used by client\r
312 VEND_63_IX, // not used by client\r
313 VEND_64_IX, // not used by client\r
314 VEND_65_IX, // not used by client\r
315 VEND_66_IX, // not used by client\r
316 VEND_67_IX, // not used by client\r
317 VEND_68_IX, // not used by client\r
318 VEND_69_IX, // not used by client\r
319 VEND_70_IX, // not used by client\r
320 VEND_PXE_BOOT_ITEM_IX\r
321};\r
322\r
323/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
324\r
325//\r
326// array of options in which we are interested\r
327// value 0 -> not of interest, else value is index into OPTION array\r
328// option values from 1 to MAX_OUR_OPT\r
329//\r
330STATIC UINT8 OurDhcpOptions[MAX_OUR_OPT] = {\r
331 OP_SUBNET_MASK_IX, // OP_SUBNET_MASK 1 // data is the subnet mask\r
332 OP_TIME_OFFSET_IX, // OP_TIME_OFFSET 2 // data is the time offset of subnet to UTC in seconds\r
333 OP_ROUTER_LIST_IX, // OP_ROUTER_LIST 3 // list of routers on subnet\r
334 OP_TIME_SERVERS_IX, // OP_TIME_SERVERS 4 // list of time servers available\r
335 OP_NAME_SERVERS_IX, // OP_NAME_SERVERS 5 // list of name servers available\r
336 OP_DNS_SERVERS_IX, // OP_DNS_SERVERS 6 // list of DNS servers available\r
337 OP_LOG_SERVERS_IX, // OP_LOG_SERVERS 7\r
338 OP_COOKIE_SERVERS_IX, // OP_COOKIE_SERVERS 8\r
339 OP_LPR_SREVERS_IX, // OP_LPR_SREVERS 9\r
340 OP_IMPRESS_SERVERS_IX, // OP_IMPRESS_SERVERS 10\r
341 OP_RES_LOC_SERVERS_IX, // OP_RES_LOC_SERVERS 11\r
342 OP_HOST_NAME_IX, // OP_HOST_NAME 12 // client name\r
343 OP_BOOT_FILE_SZ_IX, // OP_BOOT_FILE_SZ 13 // number of 512 blocks of boot file\r
344 OP_DUMP_FILE_IX, // OP_DUMP_FILE 14 // path name of dump file if client crashes\r
345 OP_DOMAIN_NAME_IX, // OP_DOMAIN_NAME 15 // domain name to use\r
346 OP_SWAP_SERVER_IX, // OP_SWAP_SERVER 16\r
347 OP_ROOT_PATH_IX, // OP_ROOT_PATH 17 // path name containing root disk\r
348 OP_EXTENSION_PATH_IX, // OP_EXTENSION_PATH 18 // name of TFTP downloadable file of form of OP\r
349 OP_IP_FORWARDING_IX, // OP_IP_FORWARDING 19 // enable/disable IP packet forwarding\r
350 OP_NON_LOCAL_SRC_RTE_IX, // OP_NON_LOCAL_SRC_RTE 20 // enable/disable non local source routing\r
351 OP_POLICY_FILTER_IX, // OP_POLICY_FILTER 21 // policy filters for non local source routing\r
352 OP_MAX_DATAGRAM_SZ_IX, // OP_MAX_DATAGRAM_SZ 22 // maximum datagram reassembly size\r
353 OP_DEFAULT_TTL_IX, // OP_DEFAULT_TTL 23 // default IP time to live\r
354 OP_MTU_AGING_TIMEOUT_IX, // OP_MTU_AGING_TIMEOUT 24\r
355 OP_MTU_SIZES_IX, // OP_MTU_SIZES 25\r
356 OP_MTU_TO_USE_IX, // OP_MTU_TO_USE 26\r
357 OP_ALL_SUBNETS_LOCAL_IX, // OP_ALL_SUBNETS_LOCAL 27\r
358 OP_BROADCAST_ADD_IX, // OP_BROADCAST_ADD 28 // broadcast address used on subnet\r
359 OP_PERFORM_MASK_DISCOVERY_IX, // OP_PERFORM_MASK_DISCOVERY 29 // perform mask discovery using ICMP\r
360 OP_RESPOND_TO_MASK_REQ_IX, // OP_RESPOND_TO_MASK_REQ 30 // respond to subnet mask requests using ICMP\r
361 OP_PERFORM_ROUTER_DISCOVERY_IX, // OP_PERFORM_ROUTER_DISCOVERY 31\r
362 OP_ROUTER_SOLICIT_ADDRESS_IX, // OP_ROUTER_SOLICIT_ADDRESS 32\r
363 OP_STATIC_ROUTER_LIST_IX, // OP_STATIC_ROUTER_LIST 33 // list of dest/route pairs\r
364 OP_USE_ARP_TRAILERS_IX, // OP_USE_ARP_TRAILERS 34\r
365 OP_ARP_CACHE_TIMEOUT_IX, // OP_ARP_CACHE_TIMEOUT 35\r
366 OP_ETHERNET_ENCAPSULATION_IX, // OP_ETHERNET_ENCAPSULATION 36 // 0 -> RFC 894, 1 -> IEEE 802.3 (RFC 1042)\r
367 OP_TCP_DEFAULT_TTL_IX, // OP_TCP_DEFAULT_TTL 37 // default time to live when sending TCP segments\r
368 OP_TCP_KEEP_ALIVE_INT_IX, // OP_TCP_KEEP_ALIVE_INT 38 // keep alive interval in seconds\r
369 OP_KEEP_ALIVE_GARBAGE_IX, // OP_KEEP_ALIVE_GARBAGE 39\r
370 OP_NIS_DOMAIN_NAME_IX, // OP_NIS_DOMAIN_NAME 40\r
371 OP_NIS_SERVERS_IX, // OP_NIS_SERVERS 41\r
372 OP_NTP_SERVERS_IX, // OP_NTP_SERVERS 42\r
373 OP_VENDOR_SPECIFIC_IX, // OP_VENDOR_SPECIFIC 43\r
374 OP_NBNS_SERVERS_IX, // OP_NBNS_SERVERS 44\r
375 OP_NBDD_SERVERS_IX, // OP_NBDD_SERVERS 45\r
376 OP_NETBIOS_NODE_TYPE_IX, // OP_NETBIOS_NODE_TYPE 46\r
377 OP_NETBIOS_SCOPE_IX, // OP_NETBIOS_SCOPE 47\r
378 OP_XWINDOW_SYSTEM_FONT_SERVERS_IX, // OP_XWINDOW_SYSTEM_FONT_SERVERS 48\r
379 OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS_IX, // OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49\r
380 OP_DHCP_REQ_IP_ADD_IX, // OP_DHCP_REQ_IP_ADD 50 // requested IP address - in DHCPDISCOVER\r
381 OP_DHCP_LEASE_TIME_IX, // OP_DHCP_LEASE_TIME 51 // lease time requested/granted\r
382 OP_DHCP_OPTION_OVERLOAD_IX, // OP_DHCP_OPTION_OVERLOAD 52 // file/server name/both used to hold options\r
383 OP_DHCP_MESSAGE_TYPE_IX, // OP_DHCP_MESSAGE_TYPE 53 // message type\r
384 OP_DHCP_SERVER_IP_IX, // OP_DHCP_SERVER_IP 54 // IP of server\r
385 OP_DHCP_PARM_REQ_LIST_IX, // OP_DHCP_PARM_REQ_LIST 55 // list of requested parameters\r
386 OP_DHCP_ERROR_MESSAGE_IX, // OP_DHCP_ERROR_MESSAGE 56 // in DHCPNAK or DECLINE messages\r
387 OP_DHCP_MAX_MESSAGE_SZ_IX, // OP_DHCP_MAX_MESSAGE_SZ 57 // maximum DHCP message size client will accept\r
388 OP_DHCP_RENEWAL_TIME_IX, // OP_DHCP_RENEWAL_TIME 58 // time in seconds before transitioning to RENEWING state\r
389 OP_DHCP_REBINDING_TIME_IX, // OP_DHCP_REBINDING_TIME 59 // time in seconds before transitioning to REBINDING state\r
390 OP_DHCP_CLASS_IDENTIFIER_IX, // OP_DHCP_CLASS_IDENTIFIER 60\r
391 OP_DHCP_CLIENT_IDENTIFIER_IX, // OP_DHCP_CLIENT_IDENTIFIER 61\r
392 OP_RESERVED62_IX, // OP_RESERVED62\r
393 OP_RESERVED63_IX, // OP_RESERVED63\r
394 OP_NISPLUS_DOMAIN_NAME_IX, // OP_NISPLUS_DOMAIN_NAME 64\r
395 OP_NISPLUS_SERVERS_IX, // OP_NISPLUS_SERVERS 65\r
396 OP_DHCP_TFTP_SERVER_NAME_IX, // OP_DHCP_TFTP_SERVER_NAME 66\r
397 OP_DHCP_BOOTFILE_IX // OP_DHCP_BOOTFILE 67\r
398};\r
399\r
400#define RxBuf ((DHCP_RECEIVE_BUFFER *) (Private->ReceiveBuffers))\r
401\r
402#pragma pack()\r
403\r
404/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
405\r
406/**\r
407\r
408 @param Smbios Pointer to SMBIOS structure\r
409 @param StringNumber String number to return. 0 is used to skip all\r
410 strings and point to the next SMBIOS structure.\r
411\r
412 @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == 0\r
413\r
414**/\r
415CHAR8 *\r
416PxeBcLibGetSmbiosString (\r
417 IN SMBIOS_STRUCTURE_POINTER *Smbios,\r
418 IN UINT16 StringNumber\r
419 )\r
420{\r
421 UINT16 Index;\r
422 CHAR8 *String;\r
423\r
424 //\r
425 // Skip over formatted section\r
426 //\r
427 String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length);\r
428\r
429 //\r
430 // Look through unformated section\r
431 //\r
432 for (Index = 1; Index <= StringNumber || StringNumber == 0; Index++) {\r
433 if (StringNumber == Index) {\r
434 return String;\r
435 }\r
436 //\r
437 // Skip string\r
438 //\r
439 for (; *String != 0; String++)\r
440 ;\r
441 String++;\r
442\r
443 if (*String == 0) {\r
444 //\r
445 // If double NULL then we are done.\r
446 // Return pointer to next structure in Smbios.\r
447 // if you pass in a 0 you will always get here\r
448 //\r
449 Smbios->Raw = (UINT8 *)++String;\r
450 return NULL;\r
451 }\r
452 }\r
453\r
454 return NULL;\r
455}\r
456\r
457\r
458/**\r
459 This function gets system guid and serial number from the smbios table\r
460\r
461 @param SystemGuid The pointer of returned system guid\r
462 @param SystemSerialNumber The pointer of returned system serial number\r
463\r
464 @retval EFI_SUCCESS Successfully get the system guid and system serial\r
465 number\r
466 @retval EFI_NOT_FOUND Not find the SMBIOS table\r
467\r
468**/\r
469EFI_STATUS\r
470PxeBcLibGetSmbiosSystemGuidAndSerialNumber (\r
471 IN EFI_GUID *SystemGuid,\r
472 OUT CHAR8 **SystemSerialNumber\r
473 )\r
474{\r
475 EFI_STATUS Status;\r
dc361cc5 476 SMBIOS_TABLE_ENTRY_POINT *SmbiosTable;\r
772db4bb 477 SMBIOS_STRUCTURE_POINTER Smbios;\r
478 SMBIOS_STRUCTURE_POINTER SmbiosEnd;\r
479 UINT16 Index;\r
480\r
481 Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **) &SmbiosTable);\r
482\r
483 if (EFI_ERROR (Status)) {\r
484 return EFI_NOT_FOUND;\r
485 }\r
486\r
dc361cc5 487 Smbios.Hdr = (SMBIOS_STRUCTURE *) (UINTN) SmbiosTable->TableAddress;\r
772db4bb 488 SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength);\r
489\r
490 for (Index = 0; Index < SmbiosTable->TableLength; Index++) {\r
491 if (Smbios.Hdr->Type == 1) {\r
492 if (Smbios.Hdr->Length < 0x19) {\r
493 //\r
494 // Older version did not support Guid and Serial number\r
495 //\r
496 continue;\r
497 }\r
498 //\r
499 // SMBIOS tables are byte packed so we need to do a byte copy to\r
500 // prevend alignment faults on Itanium-based platform.\r
501 //\r
502 CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID));\r
503 *SystemSerialNumber = PxeBcLibGetSmbiosString (&Smbios, Smbios.Type1->SerialNumber);\r
504\r
505 return EFI_SUCCESS;\r
506 }\r
507 //\r
508 // Make Smbios point to the next record\r
509 //\r
510 PxeBcLibGetSmbiosString (&Smbios, 0);\r
511\r
512 if (Smbios.Raw >= SmbiosEnd.Raw) {\r
513 //\r
514 // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e.\r
515 // given this we must double check against the lenght of\r
516 // the structure.\r
517 //\r
518 return EFI_SUCCESS;\r
519 }\r
520 }\r
521\r
522 return EFI_SUCCESS;\r
523}\r
524\r
525/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
526\r
527//\r
528// add router list to list\r
529//\r
530STATIC\r
531VOID\r
532Ip4AddRouterList (\r
533 PXE_BASECODE_DEVICE *Private,\r
534 DHCPV4_OP_IP_LIST *IpListPtr\r
535 )\r
536{\r
537 EFI_IP_ADDRESS TmpIp;\r
538 INTN Index;\r
539 INTN num;\r
540\r
541 if (IpListPtr == NULL) {\r
542 return ;\r
543 }\r
544\r
545 for (Index = 0, num = IpListPtr->Header.Length >> 2; Index < num; ++Index) {\r
546 CopyMem (&TmpIp, &IpListPtr->IpList[Index], 4);\r
547 Ip4AddRouter (Private, &TmpIp);\r
548 }\r
549}\r
550\r
551/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
552\r
553//\r
554// send ARP for our IP - fail if someone has it\r
555//\r
556STATIC\r
557BOOLEAN\r
558SetStationIP (\r
559 PXE_BASECODE_DEVICE *Private\r
560 )\r
561{\r
562 EFI_MAC_ADDRESS DestMac;\r
563 EFI_STATUS EfiStatus;\r
564\r
565 ZeroMem (&DestMac, sizeof DestMac);\r
566\r
567 if (GetHwAddr(Private, (EFI_IP_ADDRESS *)&DHCP_REQ_OPTIONS.OpReqIP.Ip, (EFI_MAC_ADDRESS *)&DestMac)\r
568 || DoArp(Private, (EFI_IP_ADDRESS *)&DHCP_REQ_OPTIONS.OpReqIP.Ip, (EFI_MAC_ADDRESS *)&DestMac) == EFI_SUCCESS) {\r
569 return FALSE; // somebody else has this IP\r
570 }\r
571\r
572 CopyMem (\r
573 (EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->StationIp,\r
574 &DHCP_REQ_OPTIONS.OpReqIP.Ip,\r
575 sizeof (EFI_IPv4_ADDRESS)\r
576 );\r
577\r
578 Private->GoodStationIp = TRUE;\r
579\r
580 if (!Private->UseIgmpv1Reporting) {\r
581 return TRUE;\r
582 }\r
583\r
584 if (Private->Igmpv1TimeoutEvent != NULL) {\r
585 return TRUE;\r
586 }\r
587\r
588 EfiStatus = gBS->CreateEvent (\r
589 EVT_TIMER,\r
590 TPL_CALLBACK,\r
591 NULL,\r
592 NULL,\r
593 &Private->Igmpv1TimeoutEvent\r
594 );\r
595\r
596 if (EFI_ERROR (EfiStatus)) {\r
597 Private->Igmpv1TimeoutEvent = NULL;\r
598 return TRUE;\r
599 }\r
600\r
601 EfiStatus = gBS->SetTimer (\r
602 Private->Igmpv1TimeoutEvent,\r
603 TimerRelative,\r
604 (UINT64) V1ROUTER_PRESENT_TIMEOUT * 10000000\r
605 ); /* 400 seconds */\r
606\r
607 if (EFI_ERROR (EfiStatus)) {\r
608 gBS->CloseEvent (Private->Igmpv1TimeoutEvent);\r
609 Private->Igmpv1TimeoutEvent = NULL;\r
610 }\r
611\r
612 return TRUE;\r
613}\r
614\r
615/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
616STATIC\r
617VOID\r
618AddRouters (\r
619 PXE_BASECODE_DEVICE *Private,\r
620 DHCP_RECEIVE_BUFFER *RxBufPtr\r
621 )\r
622{\r
623 Ip4AddRouterList (\r
624 Private,\r
625 (DHCPV4_OP_IP_LIST *) RxBufPtr->OpAdds.PktOptAdds[OP_ROUTER_LIST_IX - 1]\r
626 );\r
627}\r
628\r
629/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
630STATIC\r
631EFI_STATUS\r
632DoUdpWrite (\r
633 PXE_BASECODE_DEVICE *Private,\r
634 EFI_IP_ADDRESS *ServerIpPtr,\r
635 EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr,\r
636 EFI_IP_ADDRESS *ClientIpPtr,\r
637 EFI_PXE_BASE_CODE_UDP_PORT *ClientPortPtr\r
638 )\r
639{\r
640 UINTN Len;\r
641\r
642 Len = sizeof DHCPV4_TRANSMIT_BUFFER;\r
643\r
644 return UdpWrite (\r
645 Private,\r
646 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT,\r
647 ServerIpPtr,\r
648 ServerPortPtr,\r
649 0,\r
650 ClientIpPtr,\r
651 ClientPortPtr,\r
652 0,\r
653 0,\r
654 &Len,\r
655 Private->TransmitBuffer\r
656 );\r
657}\r
658\r
659/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
660\r
661//\r
662// initialize the DHCP structure\r
663//\r
664typedef struct {\r
665 UINT8 x[4];\r
666} C4Str;\r
667\r
668STATIC\r
669VOID\r
670InitDhcpv4TxBuf (\r
671 PXE_BASECODE_DEVICE *Private\r
672 )\r
673{\r
674 UINTN HwAddrLen;\r
675 UINT8 *String;\r
676 CHAR8 *SystemSerialNumber;\r
677 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
678\r
679 PxebcMode = Private->EfiBc.Mode;\r
680\r
681 ZeroMem (&DHCPV4_TRANSMIT_BUFFER, sizeof (DHCPV4_STRUCT));\r
682 DHCPV4_TRANSMIT_BUFFER.op = BOOTP_REQUEST;\r
683 DHCPV4_TRANSMIT_BUFFER.htype = Private->SimpleNetwork->Mode->IfType;\r
684 DHCPV4_TRANSMIT_BUFFER.flags = HTONS (DHCP_BROADCAST_FLAG);\r
685 CopyMem (&DHCPV4_OPTIONS_BUFFER, (VOID *) &DHCPOpStart, sizeof (DHCPOpStart));\r
686\r
687 //\r
688 // default to hardware address\r
689 //\r
690 HwAddrLen = Private->SimpleNetwork->Mode->HwAddressSize;\r
691\r
692 if (HwAddrLen > sizeof DHCPV4_TRANSMIT_BUFFER.chaddr) {\r
693 HwAddrLen = sizeof DHCPV4_TRANSMIT_BUFFER.chaddr;\r
694 }\r
695\r
696 String = (UINT8 *) &Private->SimpleNetwork->Mode->CurrentAddress;\r
697\r
698 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (\r
699 (EFI_GUID *) DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid,\r
700 &SystemSerialNumber\r
701 ) == EFI_SUCCESS) {\r
702 if (PxebcMode->SendGUID) {\r
703 HwAddrLen = sizeof (EFI_GUID);\r
704 String = (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid;\r
705 }\r
706 } else {\r
707 //\r
708 // GUID not yet set - send all 0xff's to show programable (via SetVariable)\r
709 // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);\r
710 // GUID not yet set - send all 0's to show not programable\r
711 //\r
712 ZeroMem (DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof (EFI_GUID));\r
713 }\r
714\r
715 DHCPV4_TRANSMIT_BUFFER.hlen = (UINT8) HwAddrLen;\r
716 CopyMem (DHCPV4_TRANSMIT_BUFFER.chaddr, String, HwAddrLen);\r
717\r
718 CvtNum (\r
719 SYS_ARCH,\r
720 (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.ArchitectureType,\r
721 sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.ArchitectureType\r
722 );\r
723\r
724 DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.Type = Private->NiiPtr->Type;\r
725 DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MajorVersion = Private->NiiPtr->MajorVer;\r
726 DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MinorVersion = Private->NiiPtr->MinorVer;\r
727\r
728 *(C4Str *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.InterfaceName = *(C4Str *) Private->NiiPtr->StringId;\r
729\r
730 CvtNum (\r
731 DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MajorVersion,\r
732 (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMajor,\r
733 sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMajor\r
734 );\r
735\r
736 CvtNum (\r
737 DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MinorVersion,\r
738 (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMinor,\r
739 sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMinor\r
740 );\r
741}\r
742\r
743/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
744STATIC\r
745UINT32\r
746DecodePxeOptions (\r
747 DHCP_RECEIVE_BUFFER *RxBufPtr,\r
748 UINT8 *ptr,\r
749 INTN Len\r
750 )\r
751{\r
752 UINT8 Op;\r
753 UINT8 *EndPtr;\r
754 INTN Index;\r
755 UNION_PTR LocalPtr;\r
756 UINT32 status;\r
757\r
758 status = 0;\r
759\r
760 for (EndPtr = ptr + Len; ptr < EndPtr; ptr += Len + 2) {\r
761 Op = ptr[0];\r
762 Len = ptr[1];\r
763\r
764 switch (Op) {\r
765 case OP_PAD:\r
766 Len = -1;\r
767 break;\r
768\r
769 case OP_END:\r
770 return status;\r
771\r
772 default:\r
773 LocalPtr.BytePtr = ptr;\r
774 if (Op <= MAX_OUR_PXE_OPT) {\r
775 Index = ourPXEopts[Op - 1];\r
776 if (Index) {\r
777 RxBufPtr->OpAdds.PxeOptAdds[Index - 1] = LocalPtr.OpPtr;\r
778 status |= 1 << Index;\r
779 if (Index == VEND_PXE_BOOT_ITEM && LocalPtr.BootItem->Header.Length == 3) {\r
780 RxBufPtr->OpAdds.Status |= USE_THREE_BYTE;\r
781 }\r
782 }\r
783 }\r
784 break;\r
785 }\r
786 }\r
787\r
788 return status;\r
789}\r
790\r
791/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
792STATIC\r
793VOID\r
794DecodeOptions (\r
795 DHCP_RECEIVE_BUFFER *RxBufPtr,\r
796 UINT8 *ptr,\r
797 INTN Len\r
798 )\r
799{\r
800 UINT8 Op;\r
801 UINT8 *EndPtr;\r
802 INTN Index;\r
803 UNION_PTR LocalPtr;\r
804\r
805 for (EndPtr = ptr + Len; ptr < EndPtr; ptr += Len + 2) {\r
806 Op = ptr[0];\r
807 Len = ptr[1];\r
808\r
809 switch (Op) {\r
810 case OP_PAD:\r
811 Len = -1;\r
812 break;\r
813\r
814 case OP_END:\r
815 return ;\r
816\r
817 default:\r
818 LocalPtr.BytePtr = ptr;\r
819 if (Op <= MAX_OUR_OPT) {\r
820 Index = OurDhcpOptions[Op - 1];\r
821 if (Index) {\r
822 RxBufPtr->OpAdds.PktOptAdds[Index - 1] = LocalPtr.OpPtr;\r
823 if (Index == OP_VENDOR_SPECIFIC_IX) {\r
824 UINT32 status;\r
825 status = DecodePxeOptions (\r
826 RxBufPtr,\r
827 (UINT8 *) LocalPtr.VendorOptions->VendorOptions,\r
828 LocalPtr.VendorOptions->Header.Length\r
829 );\r
830 if (status) {\r
831 RxBufPtr->OpAdds.Status |= PXE_TYPE;\r
832 //\r
833 // check for all the MTFTP info options present - any missing is a nogo\r
834 //\r
835 if ((status & WfM11a_OPTS) == WfM11a_OPTS) {\r
836 RxBufPtr->OpAdds.Status |= WfM11a_TYPE;\r
837 }\r
838\r
839 if (status & DISCOVER_OPTS) {\r
840 RxBufPtr->OpAdds.Status |= DISCOVER_TYPE;\r
841 }\r
842\r
843 if (status & CREDENTIALS_OPT) {\r
844 RxBufPtr->OpAdds.Status |= CREDENTIALS_TYPE;\r
845 }\r
846 }\r
847 }\r
848 }\r
849 }\r
850 break;\r
851 }\r
852 }\r
853}\r
854\r
855/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
856VOID\r
857Parse (\r
858 DHCP_RECEIVE_BUFFER *RxBufPtr,\r
859 INTN Len\r
860 )\r
861{\r
862 UNION_PTR LocalPtr;\r
863\r
864 //\r
865 // initialize\r
866 //\r
867 SetMem (&RxBufPtr->OpAdds, sizeof RxBufPtr->OpAdds, 0);\r
868\r
869 DecodeOptions (\r
870 RxBufPtr,\r
871 RxBufPtr->u.Dhcpv4.options + 4,\r
872 Len - (sizeof RxBufPtr->u.Dhcpv4 - sizeof RxBufPtr->u.Dhcpv4.options + 4)\r
873 );\r
874\r
875 LocalPtr.OpPtr = RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_OPTION_OVERLOAD_IX - 1];\r
876\r
877 if ((LocalPtr.OpPtr) && (LocalPtr.Overload->Overload & OVLD_SRVR_NAME)) {\r
878 DecodeOptions (RxBufPtr, RxBufPtr->u.Dhcpv4.sname, sizeof RxBufPtr->u.Dhcpv4.sname);\r
879 }\r
880\r
881 if (LocalPtr.OpPtr && (LocalPtr.Overload->Overload & OVLD_FILE)) {\r
882 DecodeOptions (RxBufPtr, RxBufPtr->u.Dhcpv4.file, sizeof RxBufPtr->u.Dhcpv4.file);\r
883 } else if (!RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] && RxBufPtr->u.Dhcpv4.file[0]) {\r
884 RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] = (DHCPV4_OP_STRUCT *) (RxBufPtr->u.Dhcpv4.file - sizeof (DHCPV4_OP_HEADER));\r
885\r
687a2e5f 886 RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]->Header.Length = (UINT8) AsciiStrLen ((CHAR8 *) RxBufPtr->u.Dhcpv4.file);\r
772db4bb 887 }\r
888\r
889 LocalPtr.OpPtr = RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_CLASS_IDENTIFIER_IX - 1];\r
890\r
891 if ((LocalPtr.OpPtr) &&\r
892 LocalPtr.PxeClassStr->Header.Length >= 9 &&\r
893 !CompareMem (LocalPtr.PxeClassStr->Class, "PXEClient", 9)\r
894 ) {\r
895 RxBufPtr->OpAdds.Status |= PXE_TYPE;\r
896 }\r
897}\r
898\r
899/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
900STATIC\r
901VOID\r
902CopyParseRxBuf (\r
903 PXE_BASECODE_DEVICE *Private,\r
904 INTN RxBufIndex,\r
905 INTN PacketIndex\r
906 )\r
907{\r
908 DHCP_RECEIVE_BUFFER *RxBufPtr;\r
909\r
910 RxBufPtr = &((DHCP_RECEIVE_BUFFER *) Private->DhcpPacketBuffer)[PacketIndex];\r
911\r
912 CopyMem (\r
913 &RxBufPtr->u.Dhcpv4,\r
914 &RxBuf[RxBufIndex].u.Dhcpv4,\r
915 sizeof (RxBuf[RxBufIndex].u.Dhcpv4)\r
916 );\r
917\r
918 Parse (RxBufPtr, sizeof RxBufPtr->u.ReceiveBuffer);\r
919}\r
920\r
921/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
922STATIC\r
923VOID\r
924CopyProxyRxBuf (\r
925 PXE_BASECODE_DEVICE *Private,\r
926 INTN RxBufIndex\r
927 )\r
928{\r
929 Private->EfiBc.Mode->ProxyOfferReceived = TRUE;\r
930 CopyParseRxBuf (Private, RxBufIndex, PXE_OFFER_INDEX);\r
931}\r
932\r
933/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
934STATIC\r
935VOID\r
936CopyParse (\r
937 PXE_BASECODE_DEVICE *Private,\r
938 EFI_PXE_BASE_CODE_PACKET *PacketPtr,\r
939 EFI_PXE_BASE_CODE_PACKET *NewPacketPtr,\r
940 INTN Index\r
941 )\r
942{\r
943 DHCP_RECEIVE_BUFFER *DhcpRxBuf;\r
944\r
945 DhcpRxBuf = &((DHCP_RECEIVE_BUFFER *) Private->DhcpPacketBuffer)[Index];\r
946\r
947 CopyMem (\r
948 (EFI_PXE_BASE_CODE_PACKET *) &DhcpRxBuf->u.Dhcpv4,\r
949 NewPacketPtr,\r
950 sizeof (*NewPacketPtr)\r
951 );\r
952\r
953 CopyMem (&*PacketPtr, &*NewPacketPtr, sizeof (*NewPacketPtr));\r
954\r
955 Parse (DhcpRxBuf, sizeof DhcpRxBuf->u.ReceiveBuffer);\r
956}\r
957\r
958/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
959BOOLEAN\r
960AckEdit (\r
961 DHCP_RECEIVE_BUFFER *DhcpRxBuf\r
962 )\r
963{\r
964 UNION_PTR LocalPtr;\r
965\r
966 LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1];\r
967\r
968 //\r
969 // check that an ACK\r
970 // if a DHCP type, must be DHCPOFFER and must have server id\r
971 //\r
972 return (BOOLEAN)\r
973 (\r
974 (LocalPtr.OpPtr) &&\r
975 (LocalPtr.MessageType->Type == DHCPACK) &&\r
976 DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1]\r
977 );\r
978}\r
979\r
980/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
981\r
982//\r
983// if a discover type packet, make sure all required fields are present\r
984//\r
985BOOLEAN\r
986DHCPOfferAckEdit (\r
987 DHCP_RECEIVE_BUFFER *DhcpRxBuf\r
988 )\r
989{\r
990 PXE_OP_SERVER_LIST *BootServerOpPtr;\r
991 UNION_PTR LocalPtr;\r
992\r
993 if ((DhcpRxBuf->OpAdds.Status & DISCOVER_TYPE) == 0) {\r
994 return TRUE;\r
995 }\r
996\r
997 LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1];\r
998\r
999 if (LocalPtr.OpPtr == NULL) {\r
1000 LocalPtr.OpPtr = (DHCPV4_OP_STRUCT *) &DefaultDisCtl;\r
1001 DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1] = (DHCPV4_OP_STRUCT *) &DefaultDisCtl;\r
1002 }\r
1003 //\r
1004 // make sure all required fields are here\r
1005 // if mucticast enabled, need multicast address\r
1006 //\r
1007 if (!(LocalPtr.DiscoveryControl->ControlBits & DISABLE_MCAST) &&\r
1008 (!DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_MCAST_ADDR_IX - 1] || !IS_MULTICAST (((DHCPV4_OP_STRUCT *) DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_MCAST_ADDR_IX - 1])->Data))\r
1009 ) {\r
1010 return FALSE;\r
1011 //\r
1012 // missing required field\r
1013 //\r
1014 }\r
1015 //\r
1016 // if a list, it better be good\r
1017 //\r
1018 BootServerOpPtr = (PXE_OP_SERVER_LIST *) DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_SERVERS_IX - 1];\r
1019\r
1020 if (BootServerOpPtr != NULL) {\r
1021 PXE_SERVER_LIST *BootServerListPtr;\r
1022 INTN ServerListLen;\r
1023 INTN ServerEntryLen;\r
1024\r
1025 BootServerListPtr = BootServerOpPtr->ServerList;\r
1026 ServerListLen = BootServerOpPtr->Header.Length;\r
1027\r
1028 do {\r
1029 EFI_IPv4_ADDRESS *IpListPtr;\r
1030 INTN IpCnt;\r
1031\r
1032 IpCnt = BootServerListPtr->u.Ipv4List.IpCount;\r
1033\r
1034 ServerEntryLen = sizeof (PXEV4_SERVER_LIST) + 2 + (IpCnt - 1) * sizeof (EFI_IPv4_ADDRESS);\r
1035\r
1036 if (ServerListLen < ServerEntryLen) {\r
1037 //\r
1038 // missing required field\r
1039 //\r
1040 return FALSE;\r
1041 }\r
1042\r
1043 IpListPtr = BootServerListPtr->u.Ipv4List.IpList;\r
1044\r
1045 while (IpCnt--) {\r
1046 if (IS_MULTICAST (IpListPtr)) {\r
1047 //\r
1048 // missing required field\r
1049 //\r
1050 return FALSE;\r
1051 } else {\r
1052 ++IpListPtr;\r
1053 }\r
1054 }\r
1055\r
1056 BootServerListPtr = (PXE_SERVER_LIST *) IpListPtr;\r
1057 } while (ServerListLen -= ServerEntryLen);\r
1058 }\r
1059 //\r
1060 // else there must be a list if use list enabled or multicast and\r
1061 // broadcast disabled\r
1062 //\r
1063 else if ((LocalPtr.DiscoveryControl->ControlBits & USE_ACCEPT_LIST) ||\r
1064 ((LocalPtr.DiscoveryControl->ControlBits & (DISABLE_MCAST | DISABLE_BCAST)) == (DISABLE_MCAST | DISABLE_BCAST))\r
1065 ) {\r
1066 //\r
1067 // missing required field\r
1068 //\r
1069 return FALSE;\r
1070 }\r
1071 //\r
1072 // if not USE_BOOTFILE or no bootfile given, must have menu stuff\r
1073 //\r
1074 if (!(LocalPtr.DiscoveryControl->ControlBits & USE_BOOTFILE) ||\r
1075 !DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]\r
1076 ) {\r
1077 INTN MenuLth;\r
1078\r
1079 LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_MENU_IX - 1];\r
1080\r
1081 if (LocalPtr.OpPtr == NULL || !DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_PROMPT_IX - 1]) {\r
1082 //\r
1083 // missing required field\r
1084 //\r
1085 return FALSE;\r
1086 }\r
1087 //\r
1088 // make sure menu valid\r
1089 //\r
1090 MenuLth = LocalPtr.BootMenu->Header.Length;\r
1091 LocalPtr.BootMenuItem = LocalPtr.BootMenu->MenuItem;\r
1092\r
1093 do {\r
1094 INTN MenuItemLen;\r
1095\r
1096 MenuItemLen = LocalPtr.BootMenuItem->DataLen;\r
1097\r
1098 if (MenuItemLen == 0) {\r
1099 //\r
1100 // missing required field\r
1101 //\r
1102 return FALSE;\r
1103 }\r
1104\r
1105 MenuItemLen += sizeof (*LocalPtr.BootMenuItem) - sizeof (LocalPtr.BootMenuItem->Data);\r
1106\r
1107 MenuLth -= MenuItemLen;\r
1108 LocalPtr.BytePtr += MenuItemLen;\r
1109 } while (MenuLth > 0);\r
1110\r
1111 if (MenuLth != 0) {\r
1112 //\r
1113 // missing required field\r
1114 //\r
1115 return FALSE;\r
1116 }\r
1117 }\r
1118\r
1119 if (!DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1]) {\r
1120 DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1] = (DHCPV4_OP_STRUCT *) &DefaultBootItem;\r
1121 }\r
1122\r
1123 return TRUE;\r
1124}\r
1125\r
1126/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1127BOOLEAN\r
1128DHCPAckEdit (\r
1129 DHCP_RECEIVE_BUFFER *RxBufPtr\r
1130 )\r
1131{\r
1132 return (BOOLEAN) (DHCPOfferAckEdit (RxBufPtr) ? AckEdit (RxBufPtr) : FALSE);\r
1133}\r
1134\r
1135/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1136\r
1137//\r
1138// get an offer/ack\r
1139//\r
1140EFI_STATUS\r
1141GetOfferAck (\r
1142 PXE_BASECODE_DEVICE *Private,\r
1143 BOOLEAN (*ExtraEdit)(DHCP_RECEIVE_BUFFER *DhcpRxBuf),\r
1144 UINT16 OpFlags, // for Udp read\r
1145 EFI_IP_ADDRESS *ServerIpPtr,\r
1146 EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr,\r
1147 EFI_IP_ADDRESS *ClientIpPtr,\r
1148 EFI_PXE_BASE_CODE_UDP_PORT *ClientPortPtr,\r
1149 DHCP_RECEIVE_BUFFER *DhcpRxBuf,\r
1150 EFI_EVENT TimeoutEvent\r
1151 )\r
1152/*++\r
1153Routine description:\r
1154 Wait for an OFFER/ACK packet.\r
1155\r
1156Parameters:\r
1157 Private := Pointer to PxeBc interface\r
1158 ExtraEdit := Pointer to extra option checking function\r
1159 OpFlags := UdpRead() option flags\r
1160 ServerIpPtr :=\r
1161 ServerPortPtr :=\r
1162 ClientIpPtr :=\r
1163 ClientPortPtr :=\r
1164 DhcpRxBuf :=\r
1165 TimeoutEvent :=\r
1166\r
1167Returns:\r
1168--*/\r
1169{\r
1170 EFI_IP_ADDRESS ServerIp;\r
1171 EFI_STATUS StatCode;\r
1172 INTN RxBufLen;\r
1173\r
1174 for (;;) {\r
1175 //\r
1176 // Wait until we get a UDP packet.\r
1177 //\r
1178 ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS));\r
1179 RxBufLen = sizeof RxBuf[0].u.ReceiveBuffer;\r
1180\r
1181 if ((StatCode = UdpRead (\r
1182 Private,\r
1183 OpFlags,\r
1184 ClientIpPtr,\r
1185 ClientPortPtr,\r
1186 ServerIpPtr,\r
1187 ServerPortPtr,\r
1188 0,\r
1189 0,\r
1190 (UINTN *) &RxBufLen,\r
1191 &DhcpRxBuf->u.Dhcpv4,\r
1192 TimeoutEvent\r
1193 )) != EFI_SUCCESS) {\r
1194 if (StatCode == EFI_TIMEOUT) {\r
1195 StatCode = EFI_NO_RESPONSE;\r
1196 }\r
1197\r
1198 break;\r
1199 }\r
1200 //\r
1201 // got a packet - see if a good offer\r
1202 //\r
1203 if (DhcpRxBuf->u.Dhcpv4.op != BOOTP_REPLY) {\r
1204 continue;\r
1205 }\r
1206\r
1207 if (DhcpRxBuf->u.Dhcpv4.xid != DHCPV4_TRANSMIT_BUFFER.xid) {\r
1208 continue;\r
1209 }\r
1210\r
1211 if (*(UINT32 *) DHCPV4_TRANSMIT_BUFFER.options != * (UINT32 *) DhcpRxBuf->u.Dhcpv4.options) {\r
1212 continue;\r
1213 }\r
1214\r
1215 if (*(UINT8 *) &DhcpRxBuf->u.Dhcpv4.yiaddr > 223) {\r
1216 continue;\r
1217 }\r
1218\r
1219 if (CompareMem (\r
1220 DhcpRxBuf->u.Dhcpv4.chaddr,\r
1221 DHCPV4_TRANSMIT_BUFFER.chaddr,\r
1222 sizeof DhcpRxBuf->u.Dhcpv4.chaddr\r
1223 )) {\r
1224 //\r
1225 // no good\r
1226 //\r
1227 continue;\r
1228 }\r
1229\r
1230 Parse (DhcpRxBuf, RxBufLen);\r
1231\r
1232 if (!(*ExtraEdit) (DhcpRxBuf)) {\r
1233 continue;\r
1234 }\r
1235 //\r
1236 // Good DHCP packet.\r
1237 //\r
1238 StatCode = EFI_SUCCESS;\r
1239 break;\r
1240 }\r
1241\r
1242 return StatCode;\r
1243}\r
1244\r
1245/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1246\r
1247//\r
1248// get DHCPOFFER's\r
1249//\r
1250EFI_STATUS\r
1251GetOffers (\r
1252 PXE_BASECODE_DEVICE *Private\r
1253 )\r
1254{\r
1255 EFI_IP_ADDRESS ClientIp;\r
1256 EFI_IP_ADDRESS ServerIp;\r
1257 EFI_STATUS StatCode;\r
1258 EFI_EVENT TimeoutEvent;\r
1259 INTN NumOffers;\r
1260 INTN Index;\r
1261\r
1262 //\r
1263 //\r
1264 //\r
1265 ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS));\r
1266 NumOffers = 0;\r
1267\r
1268 for (Index = 0; Index < (sizeof Private->ServerCount) / sizeof Private->ServerCount[0]; ++Index) {\r
1269 Private->ServerCount[Index] = 0;\r
1270 Private->GotProxy[Index] = 0;\r
1271 }\r
1272\r
1273 Private->GotBootp = 0;\r
1274 //\r
1275 // these we throw away\r
1276 //\r
1277 Private->GotProxy[DHCP_ONLY_IX] = 1;\r
1278 StatCode = gBS->CreateEvent (\r
1279 EVT_TIMER,\r
1280 TPL_CALLBACK,\r
1281 NULL,\r
1282 NULL,\r
1283 &TimeoutEvent\r
1284 );\r
1285\r
1286 if (EFI_ERROR (StatCode)) {\r
1287 return StatCode;\r
1288 }\r
1289\r
1290 StatCode = gBS->SetTimer (\r
1291 TimeoutEvent,\r
1292 TimerRelative,\r
1293 Private->Timeout * 10000000 + 1000000\r
1294 );\r
1295\r
1296 if (EFI_ERROR (StatCode)) {\r
1297 gBS->CloseEvent (TimeoutEvent);\r
1298 return StatCode;\r
1299 }\r
1300 //\r
1301 // get offers\r
1302 //\r
1303 for (;;) {\r
1304 DHCP_RECEIVE_BUFFER *DhcpRxBuf;\r
1305 UNION_PTR LocalPtr;\r
1306\r
1307 DhcpRxBuf = &RxBuf[NumOffers];\r
1308\r
1309 if ((\r
1310 StatCode = GetOfferAck (\r
1311 Private,\r
1312 DHCPOfferAckEdit,\r
1313 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP |\r
1314 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP |\r
1315 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
1316 &ServerIp,\r
1317 &DhcpServerPort,\r
1318 &ClientIp,\r
1319 &DHCPClientPort,\r
1320 DhcpRxBuf,\r
1321 TimeoutEvent\r
1322 )\r
1323) != EFI_SUCCESS\r
1324 ) {\r
1325 break;\r
1326 }\r
1327\r
1328 LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1];\r
1329\r
1330 //\r
1331 // check type of offer\r
1332 //\r
1333 if (LocalPtr.OpPtr == NULL) {\r
1334 //\r
1335 // bootp - we only need one and make sure has bootfile\r
1336 //\r
1337 if (Private->GotBootp || !DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]) {\r
1338 continue;\r
1339 }\r
1340\r
1341 Private->GotBootp = (UINT8) (NumOffers + 1);\r
1342 }\r
1343 //\r
1344 // if a DHCP type, must be DHCPOFFER and must have server id\r
1345 //\r
1346 else if (LocalPtr.MessageType->Type != DHCPOFFER || !DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1]) {\r
1347 continue;\r
1348 } else {\r
1349 INTN TypeIx;\r
1350\r
1351 //\r
1352 // get type - PXE10, WfM11a, or BINL\r
1353 //\r
1354 if (DhcpRxBuf->OpAdds.Status & DISCOVER_TYPE) {\r
1355 TypeIx = PXE10_IX;\r
1356 } else if (DhcpRxBuf->OpAdds.Status & WfM11a_TYPE) {\r
1357 //\r
1358 // WfM - make sure it has a bootfile\r
1359 //\r
1360 if (!DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]) {\r
1361 continue;\r
1362 }\r
1363\r
1364 TypeIx = WfM11a_IX;\r
1365 } else {\r
1366 TypeIx = (DhcpRxBuf->OpAdds.Status & PXE_TYPE) ? BINL_IX : DHCP_ONLY_IX;\r
1367 }\r
1368 //\r
1369 // check DHCP or proxy\r
1370 //\r
1371 if (DhcpRxBuf->u.Dhcpv4.yiaddr == 0) {\r
1372 //\r
1373 // proxy - only need one of each type if not BINL\r
1374 // and must have at least PXE_TYPE\r
1375 //\r
1376 if (TypeIx == BINL_IX) {\r
1377 Private->BinlProxies[Private->GotProxy[BINL_IX]++] = (UINT8) NumOffers;\r
1378 } else if (Private->GotProxy[TypeIx]) {\r
1379 continue;\r
1380 } else {\r
1381 Private->GotProxy[TypeIx] = (UINT8) (NumOffers + 1);\r
1382 }\r
1383 } else {\r
1384 Private->OfferCount[TypeIx][Private->ServerCount[TypeIx]++] = (UINT8) NumOffers;\r
1385 }\r
1386 }\r
1387\r
1388 if (++NumOffers == MAX_OFFERS) {\r
1389 break;\r
1390 }\r
1391 }\r
1392\r
1393 gBS->CloseEvent (TimeoutEvent);\r
1394 Private->NumOffersReceived = NumOffers;\r
1395\r
1396 return (Private->NumOffersReceived) ? EFI_SUCCESS : EFI_NO_RESPONSE;\r
1397}\r
1398\r
1399/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1400\r
1401//\r
1402// send DHCPDECLINE\r
1403//\r
1404STATIC\r
1405VOID\r
1406DeclineOffer (\r
1407 PXE_BASECODE_DEVICE *Private\r
1408 )\r
1409{\r
1410 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
1411 UINT16 SaveSecs;\r
1412\r
1413 PxebcMode = Private->EfiBc.Mode;\r
1414 SaveSecs = DHCPV4_TRANSMIT_BUFFER.secs;\r
1415\r
1416 DHCPV4_TRANSMIT_BUFFER.secs = 0;\r
1417 DHCPV4_TRANSMIT_BUFFER.flags = 0;\r
1418 SetMem (\r
1419 DHCPV4_TRANSMIT_BUFFER.options + sizeof (struct opdeclinestr),\r
1420 sizeof (DHCPOpStart) - sizeof (struct opdeclinestr),\r
1421 OP_PAD\r
1422 );\r
1423 DHCPDECLINEoptions.DhcpMessageType.Type = DHCPDECLINE;\r
07e3550e 1424 CopyMem (&DHCPDECLINEoptions.OpDeclineEnd, &DHCP_REQ_OPTIONS, sizeof (DHCPDECLINEoptions.OpDeclineEnd));\r
772db4bb 1425\r
1426 {\r
1427 EFI_IP_ADDRESS TmpIp;\r
1428\r
1429 CopyMem (&TmpIp, &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip, sizeof TmpIp);\r
1430\r
1431 DoUdpWrite (\r
1432 Private,\r
1433 &TmpIp,\r
1434 &DhcpServerPort,\r
1435 &PxebcMode->StationIp,\r
1436 &DHCPClientPort\r
1437 );\r
1438 }\r
1439\r
1440 InitDhcpv4TxBuf (Private);\r
1441 DHCPV4_TRANSMIT_BUFFER.secs = SaveSecs;\r
1442 Private->GoodStationIp = FALSE;\r
1443}\r
1444\r
1445/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1446\r
1447//\r
1448// send DHCPRELEASE\r
1449//\r
1450STATIC\r
1451BOOLEAN\r
1452Release (\r
1453 PXE_BASECODE_DEVICE *Private\r
1454 )\r
1455{\r
1456 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
1457 UINT16 SaveSecs;\r
1458\r
1459 PxebcMode = Private->EfiBc.Mode;\r
1460 SaveSecs = DHCPV4_TRANSMIT_BUFFER.secs;\r
1461 DHCPV4_TRANSMIT_BUFFER.secs = 0;\r
1462\r
1463 SetMem (\r
1464 DHCPV4_TRANSMIT_BUFFER.options + sizeof (struct opreleasestr),\r
1465 sizeof (DHCPOpStart) - sizeof (struct opreleasestr),\r
1466 OP_PAD\r
1467 );\r
1468\r
1469 DHCPRELEASEoptions.DhcpMessageType.Type = DHCPRELEASE;\r
1470\r
1471 CopyMem (\r
1472 &DHCPRELEASEoptions.DhcServerIpPtr,\r
84b5c78e 1473 (DHCPV4_OP_SERVER_IP *) DHCPV4_ACK_BUFFER.OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1],\r
772db4bb 1474 sizeof DHCPRELEASEoptions.DhcServerIpPtr\r
1475 );\r
1476\r
1477 DHCPRELEASEoptions.End[0] = OP_END;\r
1478\r
1479 {\r
1480 EFI_IP_ADDRESS TmpIp;\r
1481\r
1482 CopyMem (&TmpIp, &DHCPRELEASEoptions.DhcServerIpPtr.Ip, sizeof TmpIp);\r
1483\r
1484 DoUdpWrite (\r
1485 Private,\r
1486 &TmpIp,\r
1487 &DhcpServerPort,\r
1488 &PxebcMode->StationIp,\r
1489 &DHCPClientPort\r
1490 );\r
1491 }\r
1492\r
1493 InitDhcpv4TxBuf (Private);\r
1494\r
1495 DHCPV4_TRANSMIT_BUFFER.secs = SaveSecs;\r
1496 Private->GoodStationIp = FALSE;\r
1497 return FALSE;\r
1498}\r
1499\r
1500/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1501STATIC\r
1502BOOLEAN\r
1503GetBINLAck (\r
1504 PXE_BASECODE_DEVICE *Private,\r
1505 EFI_IP_ADDRESS *ServerIpPtr\r
1506 )\r
1507{\r
1508 DHCP_RECEIVE_BUFFER *DhcpRxBuf;\r
1509 EFI_STATUS StatCode;\r
1510 EFI_EVENT TimeoutEvent;\r
1511\r
1512 //\r
1513 //\r
1514 //\r
1515 StatCode = gBS->CreateEvent (\r
1516 EVT_TIMER,\r
1517 TPL_CALLBACK,\r
1518 NULL,\r
1519 NULL,\r
1520 &TimeoutEvent\r
1521 );\r
1522\r
1523 if (EFI_ERROR (StatCode)) {\r
1524 return FALSE;\r
1525 }\r
1526\r
1527 StatCode = gBS->SetTimer (\r
1528 TimeoutEvent,\r
1529 TimerRelative,\r
1530 Private->Timeout * 10000000 + 1000000\r
1531 );\r
1532\r
1533 if (EFI_ERROR (StatCode)) {\r
1534 gBS->CloseEvent (TimeoutEvent);\r
1535 return FALSE;\r
1536 }\r
1537 //\r
1538 //\r
1539 //\r
1540 DhcpRxBuf = &PXE_BINL_BUFFER;\r
1541\r
1542 for (;;) {\r
1543 EFI_PXE_BASE_CODE_UDP_PORT BINLSrvPort;\r
1544\r
1545 BINLSrvPort = 0;\r
1546\r
1547 if (GetOfferAck (\r
1548 Private,\r
1549 AckEdit,\r
1550 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
1551 ServerIpPtr,\r
1552 &BINLSrvPort,\r
1553 &Private->EfiBc.Mode->StationIp,\r
1554 &PSEUDO_DHCP_CLIENT_PORT,\r
1555 DhcpRxBuf,\r
1556 TimeoutEvent\r
1557 ) != EFI_SUCCESS) {\r
1558 break;\r
1559 }\r
1560 //\r
1561 // make sure from whom we wanted\r
1562 //\r
1563 if (!DhcpRxBuf->u.Dhcpv4.yiaddr && !CompareMem (\r
1564 &ServerIpPtr->v4,\r
1565 &((DHCPV4_OP_SERVER_IP *) DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip,\r
1566 sizeof (ServerIpPtr->v4)\r
1567 )) {\r
1568 gBS->CloseEvent (TimeoutEvent);\r
1569 //\r
1570 // got an ACK from server\r
1571 //\r
1572 return TRUE;\r
1573 }\r
1574 }\r
1575\r
1576 gBS->CloseEvent (TimeoutEvent);\r
1577 return FALSE;\r
1578}\r
1579\r
1580/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1581\r
1582//\r
1583// make sure we can get BINL\r
1584// send DHCPREQUEST to PXE server\r
1585//\r
1586STATIC\r
1587BOOLEAN\r
1588TryBINL (\r
1589 PXE_BASECODE_DEVICE *Private,\r
1590 INTN OfferIx\r
1591 )\r
1592{\r
1593 DHCP_RECEIVE_BUFFER *DhcpRxBuf;\r
1594 EFI_IP_ADDRESS ServerIp;\r
1595 UINT16 SaveSecs;\r
1596 INTN Index;\r
1597\r
1598 DhcpRxBuf = &RxBuf[OfferIx];\r
1599\r
1600 //\r
1601 // use next server address first.\r
1602 //\r
1603 ServerIp.Addr[0] = DhcpRxBuf->u.Dhcpv4.siaddr;\r
1604 if (ServerIp.Addr[0] == 0) {\r
1605 //\r
1606 // next server address is NULL, use option 54.\r
1607 //\r
1608 CopyMem (\r
1609 ((EFI_IPv4_ADDRESS *) &ServerIp),\r
1610 &((DHCPV4_OP_SERVER_IP *) DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip,\r
1611 sizeof (EFI_IPv4_ADDRESS)\r
1612 );\r
1613 }\r
1614\r
1615 //\r
1616 // client IP address - filled in by client if it knows it\r
1617 //\r
1618 CopyMem (\r
1619 ((EFI_IPv4_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr),\r
1620 &DHCP_REQ_OPTIONS.OpReqIP.Ip,\r
1621 sizeof (EFI_IPv4_ADDRESS)\r
1622 );\r
1623\r
1624 SetMem (&DHCP_REQ_OPTIONS, sizeof DHCP_REQ_OPTIONS, OP_PAD);\r
1625 DHCPV4_TRANSMIT_BUFFER.flags = 0;\r
1626 DHCPV4_OPTIONS_BUFFER.End[0] = OP_END;\r
1627 AddRouters (Private, DhcpRxBuf);\r
1628 SaveSecs = DHCPV4_TRANSMIT_BUFFER.secs;\r
1629\r
1630 for (Index = 0; Index < 3; Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), ++Index) {\r
1631 DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds);\r
1632\r
1633 //\r
1634 // unicast DHCPREQUEST to PXE server\r
1635 //\r
1636 if (DoUdpWrite (\r
1637 Private,\r
1638 &ServerIp,\r
1639 &PseudoDhcpServerPort,\r
1640 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
1641 &PSEUDO_DHCP_CLIENT_PORT\r
1642 ) != EFI_SUCCESS) {\r
1643 break;\r
1644 }\r
1645\r
1646 if (!GetBINLAck (Private, &ServerIp)) {\r
1647 continue;\r
1648 }\r
1649 //\r
1650 // early exit failures\r
1651 // make sure a good ACK\r
1652 //\r
1653 if (!DHCPOfferAckEdit (&PXE_BINL_BUFFER) || (\r
1654 !(PXE_BINL_BUFFER.OpAdds.Status & DISCOVER_TYPE) && !PXE_BINL_BUFFER.OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]\r
1655 )\r
1656 ) {\r
1657 break;\r
1658 }\r
1659\r
1660 Private->EfiBc.Mode->ProxyOfferReceived = TRUE;\r
1661 return TRUE;\r
1662 }\r
1663 //\r
1664 // failed - reset seconds field, etc.\r
1665 //\r
1666 Private->EfiBc.Mode->RouteTableEntries = 0;\r
1667 //\r
1668 // reset\r
1669 //\r
1670 DHCPV4_TRANSMIT_BUFFER.secs = SaveSecs;\r
1671 return FALSE;\r
1672}\r
1673\r
1674/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1675STATIC\r
1676BOOLEAN\r
1677TryFinishBINL (\r
1678 PXE_BASECODE_DEVICE *Private,\r
1679 INTN OfferIx\r
1680 )\r
1681{\r
1682 if (TryBINL (Private, OfferIx)) {\r
1683 return TRUE;\r
1684 }\r
1685\r
1686 return Release (Private);\r
1687}\r
1688\r
1689/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1690STATIC\r
1691BOOLEAN\r
1692TryFinishProxyBINL (\r
1693 PXE_BASECODE_DEVICE *Private\r
1694 )\r
1695{\r
1696 INTN Index;\r
1697\r
1698 for (Index = 0; Index < Private->GotProxy[BINL_IX]; ++Index) {\r
1699 if (TryBINL (Private, Private->BinlProxies[Index])) {\r
1700 return TRUE;\r
1701 }\r
1702 }\r
1703\r
1704 return Release (Private);\r
1705}\r
1706\r
1707/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1708\r
1709//\r
1710// try to finish DORA - send DHCP request, wait for ACK, check with ARP\r
1711//\r
1712STATIC\r
1713BOOLEAN\r
1714TryFinishDORA (\r
1715 PXE_BASECODE_DEVICE *Private,\r
1716 INTN OfferIx\r
1717 )\r
1718{\r
1719 DHCP_RECEIVE_BUFFER *DhcpRxBuf;\r
1720 EFI_IP_ADDRESS ClientIp;\r
1721 EFI_IP_ADDRESS ServerIp;\r
1722 EFI_STATUS StatCode;\r
1723 UNION_PTR LocalPtr;\r
1724 EFI_EVENT TimeoutEvent;\r
1725\r
1726 //\r
1727 // send DHCP request\r
1728 // if fail return false\r
1729 //\r
1730 DhcpRxBuf = &DHCPV4_ACK_BUFFER;\r
1731 DHCPV4_OPTIONS_BUFFER.DhcpMessageType.Type = DHCPREQUEST;\r
07e3550e 1732 CopyMem (&DHCP_REQ_OPTIONS, &RequestOpEndStr, sizeof (DHCP_REQ_OPTIONS));\r
772db4bb 1733 DHCP_REQ_OPTIONS.OpReqIP.Ip = *(EFI_IPv4_ADDRESS *) &RxBuf[OfferIx].u.Dhcpv4.yiaddr;\r
1734\r
1735 CopyMem (\r
1736 &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip,\r
1737 &((DHCPV4_OP_SERVER_IP *) RxBuf[OfferIx].OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip,\r
1738 sizeof DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip\r
1739 );\r
1740\r
1741 CopyMem (\r
1742 Private->EfiBc.Mode->SubnetMask.Addr,\r
1743 &DefaultSubnetMask,\r
1744 4\r
1745 );\r
1746\r
1747 //\r
1748 // broadcast DHCPREQUEST\r
1749 //\r
1750 if (DoUdpWrite (\r
1751 Private,\r
1752 &BroadcastIP,\r
1753 &DhcpServerPort,\r
1754 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
1755 &DHCPClientPort\r
1756 ) != EFI_SUCCESS) {\r
1757 return FALSE;\r
1758 }\r
1759 //\r
1760 //\r
1761 //\r
1762 StatCode = gBS->CreateEvent (\r
1763 EVT_TIMER,\r
1764 TPL_CALLBACK,\r
1765 NULL,\r
1766 NULL,\r
1767 &TimeoutEvent\r
1768 );\r
1769\r
1770 if (EFI_ERROR (StatCode)) {\r
1771 return FALSE;\r
1772 }\r
1773\r
1774 StatCode = gBS->SetTimer (\r
1775 TimeoutEvent,\r
1776 TimerPeriodic,\r
1777 Private->Timeout * 10000000 + 1000000\r
1778 );\r
1779\r
1780 if (EFI_ERROR (StatCode)) {\r
1781 gBS->CloseEvent (TimeoutEvent);\r
1782 return FALSE;\r
1783 }\r
1784 //\r
1785 // wait for ACK\r
1786 //\r
1787 for (;;) {\r
1788 if (GetOfferAck (\r
1789 Private,\r
1790 DHCPAckEdit,\r
1791 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP,\r
1792 &ServerIp,\r
1793 &DhcpServerPort,\r
1794 &ClientIp,\r
1795 &DHCPClientPort,\r
1796 DhcpRxBuf,\r
1797 TimeoutEvent\r
1798 ) != EFI_SUCCESS) {\r
1799 break;\r
1800 }\r
1801 //\r
1802 // check type of response - need DHCPACK\r
1803 //\r
1804 if (CompareMem (\r
1805 &DHCP_REQ_OPTIONS.OpReqIP.Ip,\r
1806 &DhcpRxBuf->u.Dhcpv4.yiaddr,\r
1807 sizeof (EFI_IPv4_ADDRESS)\r
1808 ) || CompareMem (\r
1809 &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip,\r
1810 &((DHCPV4_OP_SERVER_IP *) DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip,\r
1811 sizeof (EFI_IPv4_ADDRESS)\r
1812 )) {\r
1813 continue;\r
1814 }\r
1815 //\r
1816 // got ACK\r
1817 // check with ARP that IP unused - good return true\r
1818 //\r
1819 if (!SetStationIP (Private)) {\r
1820 //\r
1821 // fail - send DHCPDECLINE and return false\r
1822 //\r
1823 DeclineOffer (Private);\r
1824 break;\r
1825 }\r
1826\r
1827 LocalPtr.OpPtr = DHCPV4_ACK_BUFFER.OpAdds.PktOptAdds[OP_SUBNET_MASK_IX - 1];\r
1828\r
1829 if (LocalPtr.OpPtr != NULL) {\r
1830 CopyMem (\r
1831 (EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->SubnetMask,\r
1832 &LocalPtr.SubnetMaskStr->Ip,\r
1833 sizeof (EFI_IPv4_ADDRESS)\r
1834 );\r
1835 }\r
1836\r
1837 AddRouters (Private, DhcpRxBuf);\r
1838 gBS->CloseEvent (TimeoutEvent);\r
1839 return TRUE;\r
1840 }\r
1841\r
1842 gBS->CloseEvent (TimeoutEvent);\r
1843 return FALSE;\r
1844}\r
1845\r
1846/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1847\r
1848//\r
1849// try a DHCP server of appropriate type\r
1850//\r
1851STATIC\r
1852BOOLEAN\r
1853TryDHCPFinishDORA (\r
1854 PXE_BASECODE_DEVICE *Private,\r
1855 INTN TypeIx\r
1856 )\r
1857{\r
1858 INTN Index;\r
1859\r
1860 //\r
1861 // go through the DHCP servers of the requested type\r
1862 //\r
1863 for (Index = 0; Index < Private->ServerCount[TypeIx]; ++Index) {\r
1864 if (TryFinishDORA (Private, Index = Private->OfferCount[TypeIx][Index])) {\r
1865 if (TypeIx == BINL_IX && !TryFinishBINL (Private, Index)) {\r
1866 continue;\r
1867 }\r
1868\r
1869 return TRUE;\r
1870 }\r
1871 }\r
1872\r
1873 return FALSE;\r
1874}\r
1875\r
1876/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1877\r
1878//\r
1879// try a DHCP only server and a proxy of appropriate type\r
1880//\r
1881STATIC\r
1882BOOLEAN\r
1883TryProxyFinishDORA (\r
1884 PXE_BASECODE_DEVICE *Private,\r
1885 INTN TypeIx\r
1886 )\r
1887{\r
1888 INTN Index;\r
1889\r
1890 if (!Private->GotProxy[TypeIx]) {\r
1891 //\r
1892 // no proxies of the type wanted\r
1893 //\r
1894 return FALSE;\r
1895 }\r
1896 //\r
1897 // go through the DHCP only servers\r
1898 //\r
1899 for (Index = 0; Index < Private->ServerCount[DHCP_ONLY_IX]; ++Index) {\r
1900 if (TryFinishDORA (Private, Private->OfferCount[DHCP_ONLY_IX][Index])) {\r
1901 if (TypeIx != BINL_IX) {\r
1902 CopyProxyRxBuf (Private, Private->GotProxy[TypeIx] - 1);\r
1903 } else if (!TryFinishProxyBINL (Private)) {\r
1904 //\r
1905 // if didn't work with this DHCP, won't work with any\r
1906 //\r
1907 return FALSE;\r
1908 }\r
1909\r
1910 return TRUE;\r
1911 }\r
1912 }\r
1913\r
1914 return FALSE;\r
1915}\r
1916\r
1917/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1918\r
1919//\r
1920// getting to the bottom of the barrel\r
1921//\r
1922STATIC\r
1923BOOLEAN\r
1924TryAnyWithBootfileFinishDORA (\r
1925 PXE_BASECODE_DEVICE *Private\r
1926 )\r
1927{\r
1928 //\r
1929 // try a DHCP only server who has a bootfile\r
1930 //\r
1931 UNION_PTR LocalPtr;\r
1932 INTN Index;\r
1933\r
1934 for (Index = 0; Index < Private->ServerCount[DHCP_ONLY_IX]; ++Index) {\r
1935 INTN offer;\r
1936\r
1937 offer = Private->OfferCount[DHCP_ONLY_IX][Index];\r
1938\r
1939 if (RxBuf[offer].OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] && TryFinishDORA (Private, offer)) {\r
1940 return TRUE;\r
1941 }\r
1942 }\r
1943 //\r
1944 // really at bottom - see if be have any bootps\r
1945 //\r
1946 if (!Private->GotBootp) {\r
1947 return FALSE;\r
1948 }\r
1949\r
1950 DHCP_REQ_OPTIONS.OpReqIP.Ip = *(EFI_IPv4_ADDRESS *) &RxBuf[Private->GotBootp - 1].u.Dhcpv4.yiaddr;\r
1951\r
1952 if (!SetStationIP (Private)) {\r
1953 return FALSE;\r
1954 }\r
1955 //\r
1956 // treat BOOTP response as DHCP ACK packet\r
1957 //\r
1958 CopyParseRxBuf (Private, Private->GotBootp - 1, DHCPV4_ACK_INDEX);\r
1959\r
1960 LocalPtr.OpPtr = RxBuf[Private->GotBootp - 1].OpAdds.PktOptAdds[OP_SUBNET_MASK_IX - 1];\r
1961\r
1962 if (LocalPtr.OpPtr != NULL) {\r
1963 *(EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->SubnetMask = LocalPtr.SubnetMaskStr->Ip;\r
1964 }\r
1965\r
1966 return TRUE;\r
1967}\r
1968\r
1969/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1970\r
1971/* DoDhcpDora()\r
1972 */\r
1973STATIC\r
1974EFI_STATUS\r
1975DoDhcpDora (\r
1976 PXE_BASECODE_DEVICE *Private,\r
1977 BOOLEAN SortOffers\r
1978 )\r
1979{\r
1980 EFI_PXE_BASE_CODE_IP_FILTER Filter;\r
1981 EFI_STATUS StatCode;\r
1982 INTN NumOffers;\r
1983\r
1984 Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP | EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST;\r
1985\r
1986 Filter.IpCnt = 0;\r
1987 Filter.reserved = 0;\r
1988\r
1989 //\r
1990 // set filter unicast or broadcast\r
1991 //\r
1992 if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) {\r
1993 return StatCode;\r
1994 }\r
1995 //\r
1996 // seed random number with hardware address\r
1997 //\r
1998 SeedRandom (Private, *(UINT16 *) &Private->SimpleNetwork->Mode->CurrentAddress);\r
1999\r
2000 for (Private->Timeout = 1;\r
2001 Private->Timeout < 17;\r
2002 Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), Private->Timeout <<= 1\r
2003 ) {\r
2004 INTN Index;\r
2005\r
2006 InitDhcpv4TxBuf (Private);\r
2007 DHCPV4_TRANSMIT_BUFFER.xid = Random (Private);\r
2008 DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds);\r
2009\r
2010 //\r
2011 // broadcast DHCPDISCOVER\r
2012 //\r
2013 StatCode = DoUdpWrite (\r
2014 Private,\r
2015 &BroadcastIP,\r
2016 &DhcpServerPort,\r
2017 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2018 &DHCPClientPort\r
2019 );\r
2020\r
2021 if (StatCode != EFI_SUCCESS) {\r
2022 return StatCode;\r
2023 }\r
2024\r
2025 CopyMem (\r
2026 &Private->EfiBc.Mode->DhcpDiscover,\r
2027 (EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER,\r
2028 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2029 );\r
2030\r
2031 //\r
2032 // get DHCPOFFER's\r
2033 //\r
2034 if ((StatCode = GetOffers (Private)) != EFI_SUCCESS) {\r
2035 if (StatCode != EFI_NO_RESPONSE) {\r
2036 return StatCode;\r
2037 }\r
2038\r
2039 continue;\r
2040 }\r
2041 //\r
2042 // select offer and reply DHCPREQUEST\r
2043 //\r
2044 if (SortOffers) {\r
2045 if (TryDHCPFinishDORA(Private, PXE10_IX) || // try DHCP with PXE10\r
2046 TryDHCPFinishDORA(Private, WfM11a_IX) || // no - try with WfM\r
2047 TryProxyFinishDORA(Private, PXE10_IX) || // no - try DHCP only and proxy with PXE10\r
2048 TryProxyFinishDORA(Private, WfM11a_IX) || // no - try DHCP only and proxy with WfM\r
2049 TryDHCPFinishDORA(Private, BINL_IX) || // no - try with WfM\r
2050 TryProxyFinishDORA(Private, BINL_IX) || // no - try DHCP only and proxy with PXE10\r
2051 TryAnyWithBootfileFinishDORA(Private))\r
2052 {\r
2053 return EFI_SUCCESS;\r
2054 }\r
2055\r
2056 continue;\r
2057 }\r
2058 //\r
2059 // FIFO order\r
2060 //\r
2061 NumOffers = Private->NumOffersReceived;\r
2062\r
2063 for (Index = 0; Index < NumOffers; ++Index) {\r
2064 //\r
2065 // ignore proxies\r
2066 //\r
2067 if (!RxBuf[Index].u.Dhcpv4.yiaddr) {\r
2068 continue;\r
2069 }\r
2070 //\r
2071 // check if a bootp server\r
2072 //\r
2073 if (!RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1]) {\r
2074 //\r
2075 // it is - just check ARP\r
2076 //\r
2077 if (!SetStationIP (Private)) {\r
2078 continue;\r
2079 }\r
2080 }\r
2081 //\r
2082 // else check if a DHCP only server\r
2083 //\r
2084 else if (!(RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE | PXE_TYPE))) {\r
2085 //\r
2086 // it is a normal DHCP offer (without any PXE options), just finish the D.O.R.A by sending DHCP request.\r
2087 //\r
2088 if (!TryFinishDORA (Private, Index)) {\r
2089 continue;\r
2090 }\r
2091 } else if (TryFinishDORA (Private, Index)) {\r
2092 if (!(RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE)) && !TryFinishBINL (Private, Index)) {\r
2093 continue;\r
2094 }\r
2095 }\r
2096\r
2097 DEBUG ((DEBUG_WARN, "\nDoDhcpDora() Got packets. "));\r
2098 return EFI_SUCCESS;\r
2099 }\r
2100 //\r
2101 // now look for DHCP onlys and a Proxy\r
2102 //\r
2103 for (Index = 0; Index < NumOffers; ++Index) {\r
2104 INT8 Index2;\r
2105\r
2106 //\r
2107 // ignore proxies, bootps, non DHCP onlys, and bootable DHCPS\r
2108 //\r
2109 if (!RxBuf[Index].u.Dhcpv4.yiaddr ||\r
2110 !RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1] ||\r
2111 RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE | PXE_TYPE) ||\r
2112 RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]\r
2113 ) {\r
2114 continue;\r
2115 }\r
2116 //\r
2117 // found non bootable DHCP only - try to find a proxy\r
2118 //\r
2119 for (Index2 = 0; Index2 < NumOffers; ++Index2) {\r
2120 if (!RxBuf[Index2].u.Dhcpv4.yiaddr) {\r
2121 if (!TryFinishDORA (Private, Index)) {\r
2122 //\r
2123 // DHCP no ACK\r
2124 //\r
2125 break;\r
2126 }\r
2127\r
2128 if (RxBuf[Index2].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE)) {\r
2129 CopyProxyRxBuf (Private, Index2);\r
2130 } else if (!TryFinishBINL (Private, Index2)) {\r
2131 continue;\r
2132 }\r
2133\r
2134 DEBUG ((DEBUG_WARN, "\nDoDhcpDora() Got packets. "));\r
2135 return EFI_SUCCESS;\r
2136 }\r
2137 }\r
2138 }\r
2139 }\r
2140\r
2141 return EFI_NO_RESPONSE;\r
2142}\r
2143\r
2144/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2145\r
2146//\r
2147// determine if the server ip is in the ip list\r
2148//\r
2149BOOLEAN\r
2150InServerList (\r
2151 EFI_IP_ADDRESS *ServerIpPtr,\r
2152 PXE_SERVER_LISTS *ServerListPtr\r
2153 )\r
2154{\r
2155 UINTN Index;\r
2156\r
2157 if (!ServerListPtr || !ServerListPtr->Ipv4List.IpCount) {\r
2158 return TRUE;\r
2159 }\r
2160\r
2161 for (Index = 0; Index < ServerListPtr->Ipv4List.IpCount; ++Index) {\r
2162 if (!CompareMem (\r
2163 ServerIpPtr,\r
2164 &ServerListPtr->Ipv4List.IpList[Index],\r
2165 sizeof (EFI_IPv4_ADDRESS)\r
2166 )) {\r
2167 return TRUE;\r
2168 }\r
2169 }\r
2170\r
2171 return FALSE;\r
2172}\r
2173\r
2174/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2175BOOLEAN\r
2176ExtractBootServerList (\r
2177 UINT16 Type,\r
2178 DHCPV4_OP_STRUCT *ptr,\r
2179 PXE_SERVER_LISTS **ServerListPtr\r
2180 )\r
2181{\r
2182 UNION_PTR LocalPtr;\r
2183 INTN ServerListLen;\r
2184\r
2185 LocalPtr.OpPtr = ptr;\r
2186 ServerListLen = LocalPtr.BootServersStr->Header.Length;\r
2187\r
2188 //\r
2189 // find type\r
2190 //\r
2191 LocalPtr.BootServerList = LocalPtr.BootServersStr->ServerList;\r
2192\r
2193 while (ServerListLen) {\r
2194 INTN ServerEntryLen;\r
2195\r
2196 ServerEntryLen = sizeof (PXEV4_SERVER_LIST) + 2 + (LocalPtr.BootServerList->u.Ipv4List.IpCount - 1) *\r
2197 sizeof (EFI_IPv4_ADDRESS);\r
2198\r
2199 if (NTOHS (LocalPtr.BootServerList->Type) == Type) {\r
2200 *ServerListPtr = &LocalPtr.BootServerList->u;\r
2201 return TRUE;\r
2202 }\r
2203\r
2204 (LocalPtr.BytePtr) += ServerEntryLen;\r
2205 ServerListLen -= ServerEntryLen;\r
2206 }\r
2207\r
2208 return FALSE;\r
2209}\r
2210\r
2211/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2212VOID\r
2213FreeMem (\r
2214 PXE_BASECODE_DEVICE *Private\r
2215 )\r
2216{\r
2217 if (Private->TransmitBuffer != NULL) {\r
2218 gBS->FreePool (Private->TransmitBuffer);\r
2219 Private->TransmitBuffer = NULL;\r
2220 }\r
2221\r
2222 if (Private->ReceiveBuffers != NULL) {\r
2223 gBS->FreePool (Private->ReceiveBuffers);\r
2224 Private->ReceiveBuffers = NULL;\r
2225 }\r
2226}\r
2227\r
2228/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2229BOOLEAN\r
2230GetMem (\r
2231 PXE_BASECODE_DEVICE *Private\r
2232 )\r
2233{\r
2234 EFI_STATUS Status;\r
2235\r
2236 if (Private->DhcpPacketBuffer == NULL) {\r
2237 Status = gBS->AllocatePool (\r
2238 EfiBootServicesData,\r
2239 sizeof (DHCP_RECEIVE_BUFFER) * (PXE_BIS_INDEX + 1),\r
2240 &Private->DhcpPacketBuffer\r
2241 );\r
2242\r
2243 if (EFI_ERROR (Status) || Private->DhcpPacketBuffer == NULL) {\r
2244 Private->DhcpPacketBuffer = NULL;\r
2245 FreeMem (Private);\r
2246 return FALSE;\r
2247 }\r
2248 }\r
2249\r
2250 Status = gBS->AllocatePool (\r
2251 EfiBootServicesData,\r
2252 sizeof (EFI_PXE_BASE_CODE_PACKET),\r
2253 &Private->TransmitBuffer\r
2254 );\r
2255\r
2256 if (EFI_ERROR (Status) || Private->TransmitBuffer == NULL) {\r
2257 gBS->FreePool (Private->DhcpPacketBuffer);\r
2258 Private->DhcpPacketBuffer = NULL;\r
2259 Private->TransmitBuffer = NULL;\r
2260 FreeMem (Private);\r
2261 return FALSE;\r
2262 }\r
2263\r
2264 Status = gBS->AllocatePool (\r
2265 EfiBootServicesData,\r
2266 sizeof (DHCP_RECEIVE_BUFFER) * (MAX_OFFERS),\r
2267 &Private->ReceiveBuffers\r
2268 );\r
2269\r
2270 if (EFI_ERROR (Status) || Private->ReceiveBuffers == NULL) {\r
2271 gBS->FreePool (Private->TransmitBuffer);\r
2272 gBS->FreePool (Private->DhcpPacketBuffer);\r
2273 Private->DhcpPacketBuffer = NULL;\r
2274 Private->TransmitBuffer = NULL;\r
2275 Private->ReceiveBuffers = NULL;\r
2276 FreeMem (Private);\r
2277 return FALSE;\r
2278 }\r
2279\r
2280 return TRUE;\r
2281}\r
2282\r
2283/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2284\r
2285/**\r
2286\r
2287\r
2288**/\r
2289EFI_STATUS\r
2290EFIAPI\r
2291BcDhcp (\r
2292 IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
2293 IN BOOLEAN SortOffers\r
2294 )\r
2295{\r
2296 EFI_PXE_BASE_CODE_IP_FILTER Filter;\r
2297 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
2298 PXE_BASECODE_DEVICE *Private;\r
2299 EFI_STATUS StatCode;\r
2300\r
2301 //\r
2302 // Lock the instance data and make sure started\r
2303 //\r
2304 StatCode = EFI_SUCCESS;\r
2305\r
2306 if (This == NULL) {\r
2307 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
2308 return EFI_INVALID_PARAMETER;\r
2309 }\r
2310\r
2311 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
2312\r
2313 if (Private == NULL) {\r
2314 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE pointer == NULL"));\r
2315 return EFI_INVALID_PARAMETER;\r
2316 }\r
2317\r
2318 EfiAcquireLock (&Private->Lock);\r
2319\r
2320 if (This->Mode == NULL || !This->Mode->Started) {\r
2321 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
2322 EfiReleaseLock (&Private->Lock);\r
2323 return EFI_NOT_STARTED;\r
2324 }\r
2325\r
2326 Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;\r
2327 Filter.IpCnt = 0;\r
2328 Filter.reserved = 0;\r
2329\r
2330 DEBUG ((DEBUG_INFO, "\nBcDhcp() Enter. "));\r
2331\r
2332 PxebcMode = Private->EfiBc.Mode;\r
2333\r
2334 if (!GetMem (Private)) {\r
2335 DEBUG ((DEBUG_ERROR, "\nBcDhcp() GetMem() failed.\n"));\r
2336 EfiReleaseLock (&Private->Lock);\r
2337 return EFI_OUT_OF_RESOURCES;\r
2338 }\r
2339\r
2340 PxebcMode->DhcpDiscoverValid = FALSE;\r
2341 PxebcMode->DhcpAckReceived = FALSE;\r
2342 PxebcMode->ProxyOfferReceived = FALSE;\r
2343\r
2344 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DHCP;\r
2345\r
2346 //\r
2347 // Issue BC command\r
2348 //\r
2349 if (Private->TotalSeconds == 0) {\r
2350 //\r
2351 // put in seconds field of DHCP send packets\r
2352 //\r
2353 Private->TotalSeconds = 4;\r
2354 }\r
2355\r
2356 if ((StatCode = DoDhcpDora (Private, SortOffers)) == EFI_SUCCESS) {\r
2357 //\r
2358 // success - copy packets\r
2359 //\r
2360 PxebcMode->DhcpDiscoverValid = PxebcMode->DhcpAckReceived = TRUE;\r
2361\r
2362 CopyMem (\r
2363 &PxebcMode->DhcpAck,\r
2364 (EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_ACK_PACKET,\r
2365 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2366 );\r
2367\r
2368 if (PxebcMode->ProxyOfferReceived) {\r
2369 CopyMem (\r
2370 &PxebcMode->ProxyOffer,\r
2371 (EFI_PXE_BASE_CODE_PACKET *) &PXE_OFFER_PACKET,\r
2372 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2373 );\r
2374 }\r
2375 }\r
2376 //\r
2377 // set filter back to unicast\r
2378 //\r
2379 IpFilter (Private, &Filter);\r
2380\r
2381 FreeMem (Private);\r
2382\r
2383 //\r
2384 // Unlock the instance data\r
2385 //\r
2386 DEBUG ((DEBUG_WARN, "\nBcDhcp() Exit = %xh ", StatCode));\r
2387\r
2388 EfiReleaseLock (&Private->Lock);\r
2389 return StatCode;\r
2390}\r
2391\r
2392/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2393STATIC\r
2394BOOLEAN\r
2395VerifyCredentialOption (\r
2396 UINT8 *tx,\r
2397 UINT8 *rx\r
2398 )\r
2399{\r
2400 UINTN n;\r
2401\r
2402 //\r
2403 // Fail verification if either pointer is NULL.\r
2404 //\r
2405 if (tx == NULL || rx == NULL) {\r
2406 return FALSE;\r
2407 }\r
2408 //\r
2409 // Fail verification if tx[0] is not a credential type option\r
2410 // or if the length is zero or not a multiple of four.\r
2411 //\r
2412 if (tx[0] != VEND_PXE_CREDENTIAL_TYPES || tx[1] == 0 || tx[1] % 4 != 0) {\r
2413 return FALSE;\r
2414 }\r
2415 //\r
2416 // Fail verification if rx[0] is not a credential type option\r
2417 // or if the length is not equal to four.\r
2418 //\r
2419 if (rx[0] != VEND_PXE_CREDENTIAL_TYPES || rx[1] != 4) {\r
2420 return FALSE;\r
2421 }\r
2422 //\r
2423 // Look through transmitted credential types for a copy\r
2424 // of the received credential type.\r
2425 //\r
2426 for (n = 0; n < tx[1]; n += 4) {\r
2427 if (!CompareMem (&tx[n + 2], &rx[2], 4)) {\r
2428 return TRUE;\r
2429 }\r
2430 }\r
2431\r
2432 return FALSE;\r
2433}\r
2434\r
2435/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2436\r
2437/**\r
2438\r
2439\r
2440**/\r
2441EFI_STATUS\r
2442DoDiscover (\r
2443 PXE_BASECODE_DEVICE *Private,\r
2444 UINT16 OpFlags,\r
2445 IN UINT16 Type,\r
2446 IN UINT16 *LayerPtr,\r
2447 IN BOOLEAN UseBis,\r
2448 EFI_IP_ADDRESS *DestPtr,\r
2449 PXE_SERVER_LISTS *ServerListPtr\r
2450 )\r
2451{\r
2452 EFI_PXE_BASE_CODE_UDP_PORT ClientPort;\r
2453 EFI_PXE_BASE_CODE_UDP_PORT ServerPort;\r
2454 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
2455 EFI_STATUS StatCode;\r
2456 EFI_EVENT TimeoutEvent;\r
2457 UINT8 OpLen;\r
2458\r
2459 PxebcMode = Private->EfiBc.Mode;\r
2460\r
2461 if (DestPtr->Addr[0] == 0) {\r
2462 DEBUG ((DEBUG_WARN, "\nDoDiscover() !DestPtr->Addr[0]"));\r
2463 return EFI_INVALID_PARAMETER;\r
2464 }\r
2465 //\r
2466 // seed random number with hardware address\r
2467 //\r
2468 SeedRandom (Private, *(UINT16 *) &Private->SimpleNetwork->Mode->CurrentAddress);\r
2469\r
2470 if (DestPtr->Addr[0] == BroadcastIP.Addr[0]) {\r
2471 ClientPort = DHCPClientPort;\r
2472 ServerPort = DhcpServerPort;\r
2473 } else {\r
2474 ClientPort = PSEUDO_DHCP_CLIENT_PORT;\r
2475 ServerPort = PseudoDhcpServerPort;\r
2476 }\r
2477\r
2478 if (UseBis) {\r
2479 *LayerPtr |= PXE_BOOT_LAYER_CREDENTIAL_FLAG;\r
2480 } else {\r
2481 *LayerPtr &= PXE_BOOT_LAYER_MASK;\r
2482 }\r
2483\r
2484 for (Private->Timeout = 1;\r
2485 Private->Timeout < 5;\r
2486 Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), ++Private->Timeout\r
2487 ) {\r
2488 InitDhcpv4TxBuf (Private);\r
2489 //\r
2490 // initialize DHCP message structure\r
2491 //\r
2492 DHCPV4_TRANSMIT_BUFFER.xid = Random (Private);\r
2493 DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds);\r
2494 CopyMem (\r
2495 &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2496 &PxebcMode->StationIp,\r
2497 sizeof DHCPV4_TRANSMIT_BUFFER.ciaddr\r
2498 );\r
2499\r
2500 DHCPV4_OPTIONS_BUFFER.DhcpMessageType.Type = DHCPREQUEST;\r
2501 DISCOVERoptions.Header.OpCode = OP_VENDOR_SPECIFIC;\r
2502 DISCOVERoptions.BootItem.Header.OpCode = VEND_PXE_BOOT_ITEM;\r
2503 DISCOVERoptions.BootItem.Header.Length = DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM);\r
2504 DISCOVERoptions.BootItem.Type = HTONS (Type);\r
2505 DISCOVERoptions.BootItem.Layer = HTONS (*LayerPtr);\r
2506\r
2507 if (UseBis) {\r
2508 EFI_BIS_PROTOCOL *BisPtr;\r
2509 BIS_APPLICATION_HANDLE BisAppHandle;\r
2510 EFI_BIS_DATA *BisDataSigInfo;\r
2511 EFI_BIS_SIGNATURE_INFO *BisSigInfo;\r
2512 UINTN Index;\r
2513 UINTN Index2;\r
2514\r
2515 BisPtr = PxebcBisStart (\r
2516 Private,\r
2517 &BisAppHandle,\r
2518 &BisDataSigInfo\r
2519 );\r
2520\r
2521 if (BisPtr == NULL) {\r
2522 //\r
2523 // %%TBD - In order to get here, BIS must have\r
2524 // been present when PXEBC.Start() was called.\r
2525 // BIS had to be shutdown/removed/damaged\r
2526 // before PXEBC.Discover() was called.\r
2527 // Do we need to document a specific error\r
2528 // for this case?\r
2529 //\r
2530 return EFI_OUT_OF_RESOURCES;\r
2531 }\r
2532 //\r
2533 // Compute number of credential types.\r
2534 //\r
2535 Index2 = BisDataSigInfo->Length / sizeof (EFI_BIS_SIGNATURE_INFO);\r
2536\r
2537 DISCREDoptions.Header.OpCode = VEND_PXE_CREDENTIAL_TYPES;\r
2538\r
2539 DISCREDoptions.Header.Length = (UINT8) (Index2 * sizeof (PXE_CREDENTIAL));\r
2540\r
2541 OpLen = (UINT8) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS) + sizeof (DHCPV4_OP_HEADER) + DISCREDoptions.Header.Length);\r
2542\r
2543 BisSigInfo = (EFI_BIS_SIGNATURE_INFO *) BisDataSigInfo->Data;\r
2544\r
2545 for (Index = 0; Index < Index2; ++Index) {\r
2546 UINT32 x;\r
2547\r
2548 CopyMem (&x, &BisSigInfo[Index], sizeof x);\r
2549 x = HTONL (x);\r
2550 CopyMem (&DISCREDoptions.Credentials[Index], &x, sizeof x);\r
2551 }\r
2552\r
2553 PxebcBisStop (BisPtr, BisAppHandle, BisDataSigInfo);\r
2554 } else {\r
2555 OpLen = DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS);\r
2556 }\r
2557\r
2558 DISCOVERoptions.Header.Length = OpLen;\r
2559\r
2560 ((UINT8 *) &DISCOVERoptions)[sizeof (DHCPV4_OP_HEADER) + OpLen - 1] = OP_END;\r
2561 ((UINT8 *) &DISCOVERoptions)[sizeof (DHCPV4_OP_HEADER) + OpLen] = OP_END;\r
2562\r
2563 StatCode = DoUdpWrite (\r
2564 Private,\r
2565 DestPtr,\r
2566 &ServerPort,\r
2567 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2568 &ClientPort\r
2569 );\r
2570\r
2571 if (StatCode != EFI_SUCCESS) {\r
2572 return StatCode;\r
2573 }\r
2574 //\r
2575 //\r
2576 //\r
2577 StatCode = gBS->CreateEvent (\r
2578 EVT_TIMER,\r
2579 TPL_CALLBACK,\r
2580 NULL,\r
2581 NULL,\r
2582 &TimeoutEvent\r
2583 );\r
2584\r
2585 if (EFI_ERROR (StatCode)) {\r
2586 return StatCode;\r
2587 }\r
2588\r
2589 StatCode = gBS->SetTimer (\r
2590 TimeoutEvent,\r
2591 TimerRelative,\r
2592 Private->Timeout * 10000000 + 1000000\r
2593 );\r
2594\r
2595 if (EFI_ERROR (StatCode)) {\r
2596 gBS->CloseEvent (TimeoutEvent);\r
2597 return StatCode;\r
2598 }\r
2599 //\r
2600 // wait for ACK\r
2601 //\r
2602 for (;;) {\r
2603 DHCP_RECEIVE_BUFFER *RxBufPtr;\r
2604 UINT16 TmpType;\r
2605 UINT16 TmpLayer;\r
2606\r
2607 RxBufPtr = UseBis ? &PXE_BIS_BUFFER : &PXE_ACK_BUFFER;\r
2608 ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS));\r
2609\r
2610 if (GetOfferAck (\r
2611 Private,\r
2612 AckEdit,\r
2613 OpFlags,\r
2614 (EFI_IP_ADDRESS *) &Private->ServerIp,\r
2615 0,\r
2616 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2617 &ClientPort,\r
2618 RxBufPtr,\r
2619 TimeoutEvent\r
2620 ) != EFI_SUCCESS) {\r
2621 break;\r
2622 }\r
2623 //\r
2624 // check type of response - need PXEClient DHCPACK of proper type with bootfile\r
2625 //\r
2626 if (!(RxBufPtr->OpAdds.Status & PXE_TYPE) ||\r
2627 (UseBis && (RxBufPtr->OpAdds.Status & USE_THREE_BYTE)) ||\r
2628 !RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] ||\r
2629 !RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1] ||\r
2630 !InServerList((EFI_IP_ADDRESS *)&((DHCPV4_OP_SERVER_IP *)RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX-1])->Ip, ServerListPtr)) {\r
2631\r
2632 continue;\r
2633 }\r
2634\r
2635 TmpType = TmpLayer = 0;\r
2636\r
2637 if (RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1]) {\r
2638 TmpType = NTOHS (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Type);\r
2639\r
2640 if (RxBufPtr->OpAdds.Status & USE_THREE_BYTE) {\r
2641 TmpLayer = (UINT16) (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Layer >> 8);\r
2642 } else {\r
2643 TmpLayer = NTOHS (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Layer);\r
2644 }\r
2645 }\r
2646\r
2647 if (TmpType != Type) {\r
2648 continue;\r
2649 }\r
2650\r
2651 if (UseBis) {\r
2652 if (!RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_CREDENTIAL_TYPES_IX - 1]) {\r
2653 continue;\r
2654 }\r
2655\r
2656 if (!VerifyCredentialOption (\r
2657 (UINT8 *) &DISCREDoptions.Header,\r
2658 (UINT8 *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_CREDENTIAL_TYPES_IX - 1]\r
2659 )) {\r
2660 continue;\r
2661 }\r
2662 }\r
2663\r
2664 *LayerPtr = TmpLayer;\r
2665\r
2666 if (UseBis) {\r
2667 CopyMem (\r
2668 &PxebcMode->PxeBisReply,\r
2669 &RxBufPtr->u.Dhcpv4,\r
2670 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2671 );\r
2672\r
2673 PxebcMode->PxeBisReplyReceived = TRUE;\r
2674\r
2675 StatCode = DoDiscover (\r
2676 Private,\r
2677 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2678 Type,\r
2679 LayerPtr,\r
2680 FALSE,\r
2681 &Private->ServerIp,\r
2682 0\r
2683 );\r
2684\r
2685 gBS->CloseEvent (TimeoutEvent);\r
2686 return StatCode;\r
2687 }\r
2688\r
2689 PxebcMode->PxeDiscoverValid = PxebcMode->PxeReplyReceived = TRUE;\r
2690\r
2691 CopyMem (\r
2692 &PxebcMode->PxeDiscover,\r
2693 &*(EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER,\r
2694 sizeof (*(EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER)\r
2695 );\r
2696\r
2697 CopyMem (\r
2698 &PxebcMode->PxeReply,\r
2699 &*(EFI_PXE_BASE_CODE_PACKET *) &RxBufPtr->u.Dhcpv4,\r
2700 sizeof (*(EFI_PXE_BASE_CODE_PACKET *) &RxBufPtr->u.Dhcpv4)\r
2701 );\r
2702\r
2703 AddRouters (Private, RxBufPtr);\r
2704\r
2705 gBS->CloseEvent (TimeoutEvent);\r
2706 return EFI_SUCCESS;\r
2707 }\r
2708\r
2709 gBS->CloseEvent (TimeoutEvent);\r
2710 }\r
2711 //\r
2712 // end for loop\r
2713 //\r
2714 return EFI_TIMEOUT;\r
2715}\r
2716\r
2717/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2718\r
2719/**\r
2720 Parameters:\r
2721 Private := Pointer to PxeBc interface\r
2722 Type :=\r
2723 LayerPtr :=\r
2724 UseBis :=\r
2725 DiscoverInfoPtr :=\r
2726 McastServerListPtr :=\r
2727 ServerListPtr :=\r
2728\r
2729\r
2730**/\r
2731STATIC\r
2732EFI_STATUS\r
2733Discover (\r
2734 PXE_BASECODE_DEVICE *Private,\r
2735 IN UINT16 Type,\r
2736 IN UINT16 *LayerPtr,\r
2737 IN BOOLEAN UseBis,\r
2738 IN EFI_PXE_BASE_CODE_DISCOVER_INFO *DiscoverInfoPtr,\r
2739 PXE_SERVER_LISTS *McastServerListPtr,\r
2740 PXE_SERVER_LISTS *ServerListPtr\r
2741 )\r
2742{\r
2743 EFI_IP_ADDRESS DestIp;\r
2744 EFI_STATUS StatCode;\r
2745\r
2746 DEBUG ((DEBUG_INFO, "\nDiscover() Type=%d Layer=%d ", Type, *LayerPtr));\r
2747\r
2748 if (UseBis) {\r
2749 DEBUG ((DEBUG_INFO, "BIS "));\r
2750 }\r
2751 //\r
2752 // get dest IP addr - mcast, bcast, or unicast\r
2753 //\r
2754 if (DiscoverInfoPtr->UseMCast) {\r
2755 DestIp.v4 = DiscoverInfoPtr->ServerMCastIp.v4;\r
2756\r
2757 DEBUG (\r
2758 (DEBUG_INFO,\r
2759 "\nDiscover() MCast %d.%d.%d.%d ",\r
2760 DestIp.v4.Addr[0],\r
2761 DestIp.v4.Addr[1],\r
2762 DestIp.v4.Addr[2],\r
2763 DestIp.v4.Addr[3])\r
2764 );\r
2765\r
2766 if ((StatCode = DoDiscover (\r
2767 Private,\r
2768 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2769 Type,\r
2770 LayerPtr,\r
2771 UseBis,\r
2772 &DestIp,\r
2773 McastServerListPtr\r
2774 )) != EFI_TIMEOUT) {\r
2775 DEBUG (\r
2776 (DEBUG_WARN,\r
2777 "\nDiscover() status == %r (%Xh)",\r
2778 StatCode,\r
2779 StatCode)\r
2780 );\r
2781\r
2782 return StatCode;\r
2783 }\r
2784 }\r
2785\r
2786 if (DiscoverInfoPtr->UseBCast) {\r
2787 DEBUG ((DEBUG_INFO, "\nDiscver() BCast "));\r
2788\r
2789 if ((StatCode = DoDiscover (\r
2790 Private,\r
2791 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2792 Type,\r
2793 LayerPtr,\r
2794 UseBis,\r
2795 &BroadcastIP,\r
2796 McastServerListPtr\r
2797 )) != EFI_TIMEOUT) {\r
2798\r
2799 DEBUG ((DEBUG_WARN, "\nDiscover() status == %r (%Xh)", StatCode, StatCode));\r
2800\r
2801 return StatCode;\r
2802 }\r
2803 }\r
2804\r
2805 if (DiscoverInfoPtr->UseUCast) {\r
2806 UINTN Index;\r
2807\r
2808 DEBUG (\r
2809 (DEBUG_INFO,\r
2810 "\nDiscover() UCast IP#=%d ",\r
2811 ServerListPtr->Ipv4List.IpCount)\r
2812 );\r
2813\r
2814 for (Index = 0; Index < ServerListPtr->Ipv4List.IpCount; ++Index) {\r
2815 CopyMem (&DestIp, &ServerListPtr->Ipv4List.IpList[Index], 4);\r
2816\r
2817 DEBUG (\r
2818 (DEBUG_INFO,\r
2819 "\nDiscover() UCast %d.%d.%d.%d ",\r
2820 DestIp.v4.Addr[0],\r
2821 DestIp.v4.Addr[1],\r
2822 DestIp.v4.Addr[2],\r
2823 DestIp.v4.Addr[3])\r
2824 );\r
2825\r
2826 if ((StatCode = DoDiscover (\r
2827 Private,\r
2828 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2829 Type,\r
2830 LayerPtr,\r
2831 UseBis,\r
2832 &DestIp,\r
2833 0\r
2834 )) != EFI_TIMEOUT) {\r
2835 DEBUG (\r
2836 (DEBUG_WARN,\r
2837 "\nDiscover() status == %r (%Xh)",\r
2838 StatCode,\r
2839 StatCode)\r
2840 );\r
2841\r
2842 return StatCode;\r
2843 }\r
2844 }\r
2845 }\r
2846\r
2847 DEBUG ((DEBUG_WARN, "\nDiscover() TIMEOUT"));\r
2848\r
2849 return EFI_TIMEOUT;\r
2850}\r
2851\r
2852/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2853\r
2854/* BcDiscover()\r
2855 */\r
2856\r
2857/**\r
2858\r
2859\r
2860**/\r
2861EFI_STATUS\r
2862EFIAPI\r
2863BcDiscover (\r
2864 IN EFI_PXE_BASE_CODE_PROTOCOL * This,\r
2865 IN UINT16 Type,\r
2866 IN UINT16 *LayerPtr,\r
2867 IN BOOLEAN UseBis,\r
2868 IN EFI_PXE_BASE_CODE_DISCOVER_INFO * DiscoverInfoPtr OPTIONAL\r
2869 )\r
2870{\r
2871 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo;\r
2872 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
2873 DHCP_RECEIVE_BUFFER *DhcpRxBuf;\r
2874 PXE_SERVER_LISTS DefaultSrvList;\r
2875 PXE_SERVER_LISTS *ServerListPtr;\r
2876 PXE_SERVER_LISTS *McastServerListPtr;\r
2877 UNION_PTR LocalPtr;\r
2878 UINTN Index;\r
2879 UINTN Index2;\r
2880 BOOLEAN AcquiredSrvList;\r
2881 EFI_STATUS StatCode;\r
2882 PXE_BASECODE_DEVICE *Private;\r
2883\r
2884 //\r
2885 // Lock the instance data and make sure started\r
2886 //\r
2887 StatCode = EFI_SUCCESS;\r
2888\r
2889 if (This == NULL) {\r
2890 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
2891 return EFI_INVALID_PARAMETER;\r
2892 }\r
2893\r
2894 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
2895\r
2896 if (Private == NULL) {\r
2897 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
2898 return EFI_INVALID_PARAMETER;\r
2899 }\r
2900\r
2901 EfiAcquireLock (&Private->Lock);\r
2902\r
2903 if (This->Mode == NULL || !This->Mode->Started) {\r
2904 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
2905 EfiReleaseLock (&Private->Lock);\r
2906 return EFI_NOT_STARTED;\r
2907 }\r
2908\r
2909 ServerListPtr = NULL;\r
2910 McastServerListPtr = NULL;\r
2911 AcquiredSrvList = FALSE;\r
2912\r
2913 PxebcMode = Private->EfiBc.Mode;\r
2914\r
2915 if (!GetMem (Private)) {\r
2916 EfiReleaseLock (&Private->Lock);\r
2917 return EFI_OUT_OF_RESOURCES;\r
2918 }\r
2919\r
2920 if (UseBis) {\r
2921 if (!PxebcMode->BisSupported) {\r
2922 EfiReleaseLock (&Private->Lock);\r
2923 return EFI_INVALID_PARAMETER;\r
2924 }\r
2925 }\r
2926\r
2927 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;\r
2928\r
2929 if (Private->TotalSeconds == 0) {\r
2930 //\r
2931 // put in seconds field of DHCP send packets\r
2932 //\r
2933 Private->TotalSeconds = 4;\r
2934 }\r
2935\r
2936 ZeroMem (&DefaultInfo, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO));\r
2937\r
2938 //\r
2939 // if layer number not zero, use previous discover\r
2940 //\r
2941 if (*LayerPtr != 0) {\r
2942 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0"));\r
2943\r
2944 if (DiscoverInfoPtr != NULL) {\r
2945 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n"));\r
2946\r
2947 EfiReleaseLock (&Private->Lock);\r
2948 return EFI_INVALID_PARAMETER;\r
2949 }\r
2950\r
2951 if (!PxebcMode->PxeDiscoverValid) {\r
2952 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n"));\r
2953\r
2954 EfiReleaseLock (&Private->Lock);\r
2955 return EFI_INVALID_PARAMETER;\r
2956 }\r
2957\r
2958 if (!PxebcMode->PxeReplyReceived) {\r
2959 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n"));\r
2960\r
2961 EfiReleaseLock (&Private->Lock);\r
2962 return EFI_INVALID_PARAMETER;\r
2963 }\r
2964\r
2965 if (UseBis && !PxebcMode->PxeBisReplyReceived) {\r
2966 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n"));\r
2967\r
2968 EfiReleaseLock (&Private->Lock);\r
2969 return EFI_INVALID_PARAMETER;\r
2970 }\r
2971\r
2972 DefaultInfo.UseUCast = TRUE;\r
2973 DiscoverInfoPtr = &DefaultInfo;\r
2974\r
2975 DefaultSrvList.Ipv4List.IpCount = 1;\r
2976 CopyMem (&DefaultSrvList.Ipv4List.IpList[0], &Private->ServerIp, 4);\r
2977\r
2978 ServerListPtr = &DefaultSrvList;\r
2979 }\r
2980 //\r
2981 // layer is zero - see if info is supplied or if we need to use info from a cached offer\r
2982 //\r
2983 else if (!DiscoverInfoPtr) {\r
2984 //\r
2985 // not supplied - generate it\r
2986 // make sure that there is cached, appropriate information\r
2987 // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail\r
2988 //\r
2989 DhcpRxBuf = (PxebcMode->ProxyOfferReceived) ? &PXE_OFFER_BUFFER : &DHCPV4_ACK_BUFFER;\r
2990\r
2991 if (!PxebcMode->DhcpAckReceived || !(DhcpRxBuf->OpAdds.Status & DISCOVER_TYPE)) {\r
2992 DEBUG ((DEBUG_WARN, "\nBcDiscover() !ack && !proxy"));\r
2993 EfiReleaseLock (&Private->Lock);\r
2994 return EFI_INVALID_PARAMETER;\r
2995 }\r
2996\r
2997 DiscoverInfoPtr = &DefaultInfo;\r
2998\r
2999 LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1];\r
3000\r
3001 //\r
3002 // if multicast enabled, need multicast address\r
3003 //\r
3004 if (!(LocalPtr.DiscoveryControl->ControlBits & DISABLE_MCAST)) {\r
3005 DefaultInfo.UseMCast = TRUE;\r
3006\r
3007 CopyMem (\r
3008 ((EFI_IPv4_ADDRESS *) &DefaultInfo.ServerMCastIp),\r
3009 &((DHCPV4_OP_IP_ADDRESS *) DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_MCAST_ADDR_IX - 1])->Ip,\r
3010 sizeof (EFI_IPv4_ADDRESS)\r
3011 );\r
3012 }\r
3013\r
3014 DefaultInfo.UseBCast = (BOOLEAN) ((LocalPtr.DiscoveryControl->ControlBits & DISABLE_BCAST) == 0);\r
3015\r
3016 DefaultInfo.MustUseList = (BOOLEAN) ((LocalPtr.DiscoveryControl->ControlBits & USE_ACCEPT_LIST) != 0);\r
3017\r
3018 DefaultInfo.UseUCast = (BOOLEAN)\r
3019 (\r
3020 (DefaultInfo.MustUseList) ||\r
3021 ((LocalPtr.DiscoveryControl->ControlBits & (DISABLE_MCAST | DISABLE_BCAST)) == (DISABLE_MCAST | DISABLE_BCAST))\r
3022 );\r
3023\r
3024 if ((DefaultInfo.UseUCast | DefaultInfo.MustUseList) && !ExtractBootServerList (\r
3025 Type,\r
3026 DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_SERVERS_IX - 1],\r
3027 &ServerListPtr\r
3028 )) {\r
3029 DEBUG ((DEBUG_WARN, "\nBcDiscover() type not in list"));\r
3030 EfiReleaseLock (&Private->Lock);\r
3031 return EFI_INVALID_PARAMETER;\r
3032 }\r
3033 }\r
3034 //\r
3035 // Info supplied - make SrvList if required\r
3036 // if we use ucast discovery or must use list, there better be one\r
3037 //\r
3038 else if (DiscoverInfoPtr->UseUCast || DiscoverInfoPtr->MustUseList) {\r
3039 //\r
3040 // there better be a list\r
3041 //\r
3042 if (DiscoverInfoPtr->IpCnt == 0) {\r
3043 DEBUG ((DEBUG_WARN, "\nBcDiscover() no bootserver list"));\r
3044 EfiReleaseLock (&Private->Lock);\r
3045 return EFI_INVALID_PARAMETER;\r
3046 }\r
3047 //\r
3048 // get its size\r
3049 //\r
3050 for (Index = Index2 = 0; Index < DiscoverInfoPtr->IpCnt; ++Index) {\r
3051 if (DiscoverInfoPtr->SrvList[Index].Type == Type) {\r
3052 if (DiscoverInfoPtr->SrvList[Index].AcceptAnyResponse) {\r
3053 if (Index2 != 0) {\r
3054 DEBUG ((DEBUG_WARN, "\nBcDiscover() accept any?"));\r
3055 EfiReleaseLock (&Private->Lock);\r
3056 return EFI_INVALID_PARAMETER;\r
3057 } else {\r
3058 Index2 = 1;\r
3059 DefaultSrvList.Ipv4List.IpCount = 0;\r
3060 ServerListPtr = &DefaultSrvList;\r
3061 break;\r
3062 }\r
3063 } else {\r
3064 ++Index2;\r
3065 }\r
3066 }\r
3067 }\r
3068\r
3069 if (Index2 == 0) {\r
3070 DEBUG ((DEBUG_WARN, "\nBcDiscover() !Index2?"));\r
3071 EfiReleaseLock (&Private->Lock);\r
3072 return EFI_INVALID_PARAMETER;\r
3073 }\r
3074\r
3075 if (ServerListPtr == NULL) {\r
3076 ServerListPtr = AllocatePool (\r
3077 sizeof (PXEV4_SERVER_LIST) + (Index2 - 1) * sizeof (EFI_IPv4_ADDRESS)\r
3078 );\r
3079\r
3080 if (ServerListPtr == NULL) {\r
3081 EfiReleaseLock (&Private->Lock);\r
3082 return EFI_OUT_OF_RESOURCES;\r
3083 }\r
3084 //\r
3085 // build an array of IP addresses from the server list\r
3086 //\r
3087 AcquiredSrvList = TRUE;\r
3088 ServerListPtr->Ipv4List.IpCount = (UINT8) Index2;\r
3089\r
3090 for (Index = Index2 = 0; Index < DiscoverInfoPtr->IpCnt; ++Index) {\r
3091 if (DiscoverInfoPtr->SrvList[Index].Type == Type) {\r
3092 CopyMem (\r
3093 &ServerListPtr->Ipv4List.IpList[Index2++],\r
3094 &DiscoverInfoPtr->SrvList[Index].IpAddr.v4,\r
3095 sizeof ServerListPtr->Ipv4List.IpList[0]\r
3096 );\r
3097 }\r
3098 }\r
3099 }\r
3100 }\r
3101\r
3102 if (DiscoverInfoPtr->MustUseList) {\r
3103 McastServerListPtr = ServerListPtr;\r
3104 }\r
3105\r
3106 if (!(DiscoverInfoPtr->UseMCast || DiscoverInfoPtr->UseBCast || DiscoverInfoPtr->UseUCast)) {\r
3107 DEBUG ((DEBUG_WARN, "\nBcDiscover() Nothing to use!\n"));\r
3108\r
3109 EfiReleaseLock (&Private->Lock);\r
3110 return EFI_INVALID_PARAMETER;\r
3111 }\r
3112\r
3113 PxebcMode->PxeDiscoverValid = PxebcMode->PxeReplyReceived = PxebcMode->PxeBisReplyReceived = FALSE;\r
3114\r
3115 StatCode = Discover (\r
3116 Private,\r
3117 Type,\r
3118 LayerPtr,\r
3119 UseBis,\r
3120 DiscoverInfoPtr,\r
3121 McastServerListPtr,\r
3122 ServerListPtr\r
3123 );\r
3124\r
3125 if (AcquiredSrvList) {\r
3126 gBS->FreePool (ServerListPtr);\r
3127 }\r
3128\r
3129 FreeMem (Private);\r
3130\r
3131 //\r
3132 // Unlock the instance data\r
3133 //\r
3134 DEBUG (\r
3135 (DEBUG_INFO,\r
3136 "\nBcDiscover() status == %r (%Xh)\n",\r
3137 StatCode,\r
3138 StatCode)\r
3139 );\r
3140\r
3141 EfiReleaseLock (&Private->Lock);\r
3142 return StatCode;\r
3143}\r
3144\r
3145/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
3146\r
3147/**\r
3148\r
3149\r
3150**/\r
3151EFI_STATUS\r
3152EFIAPI\r
3153BcSetPackets (\r
3154 IN EFI_PXE_BASE_CODE_PROTOCOL * This,\r
3155 BOOLEAN *NewDhcpDiscoverValid, OPTIONAL\r
3156 BOOLEAN *NewDhcpAckReceived, OPTIONAL\r
3157 BOOLEAN *NewProxyOfferReceived, OPTIONAL\r
3158 BOOLEAN *NewPxeDiscoverValid, OPTIONAL\r
3159 BOOLEAN *NewPxeReplyReceived, OPTIONAL\r
3160 BOOLEAN *NewPxeBisReplyReceived, OPTIONAL\r
3161 IN EFI_PXE_BASE_CODE_PACKET * NewDhcpDiscover, OPTIONAL\r
3162 IN EFI_PXE_BASE_CODE_PACKET * NewDhcpAck, OPTIONAL\r
3163 IN EFI_PXE_BASE_CODE_PACKET * NewProxyOffer, OPTIONAL\r
3164 IN EFI_PXE_BASE_CODE_PACKET * NewPxeDiscover, OPTIONAL\r
3165 IN EFI_PXE_BASE_CODE_PACKET * NewPxeReply, OPTIONAL\r
3166 IN EFI_PXE_BASE_CODE_PACKET * NewPxeBisReply OPTIONAL\r
3167 )\r
3168{\r
3169 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
3170 EFI_STATUS Status;\r
772db4bb 3171 PXE_BASECODE_DEVICE *Private;\r
3172\r
3173 //\r
3174 // Lock the instance data and make sure started\r
3175 //\r
772db4bb 3176\r
3177 if (This == NULL) {\r
3178 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
3179 return EFI_INVALID_PARAMETER;\r
3180 }\r
3181\r
3182 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
3183\r
3184 if (Private == NULL) {\r
3185 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
3186 return EFI_INVALID_PARAMETER;\r
3187 }\r
3188\r
3189 EfiAcquireLock (&Private->Lock);\r
3190\r
3191 if (This->Mode == NULL || !This->Mode->Started) {\r
3192 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
3193 EfiReleaseLock (&Private->Lock);\r
3194 return EFI_NOT_STARTED;\r
3195 }\r
3196\r
3197 PxebcMode = Private->EfiBc.Mode;\r
3198\r
3199 if (Private->DhcpPacketBuffer == NULL) {\r
3200 Status = gBS->AllocatePool (\r
3201 EfiBootServicesData,\r
3202 sizeof (DHCP_RECEIVE_BUFFER) * (PXE_BIS_INDEX + 1),\r
3203 &Private->DhcpPacketBuffer\r
3204 );\r
3205\r
3206 if (EFI_ERROR (Status) || Private->DhcpPacketBuffer == NULL) {\r
3207 Private->DhcpPacketBuffer = NULL;\r
3208 EfiReleaseLock (&Private->Lock);\r
3209 return EFI_OUT_OF_RESOURCES;\r
3210 }\r
3211 }\r
3212 //\r
3213 // Issue BC command\r
3214 //\r
3215 //\r
3216 // reset\r
3217 //\r
3218 Private->FileSize = 0;\r
3219 if (NewDhcpDiscoverValid != NULL) {\r
3220 PxebcMode->DhcpDiscoverValid = *NewDhcpDiscoverValid;\r
3221 }\r
3222\r
3223 if (NewDhcpAckReceived != NULL) {\r
3224 PxebcMode->DhcpAckReceived = *NewDhcpAckReceived;\r
3225 }\r
3226\r
3227 if (NewProxyOfferReceived != NULL) {\r
3228 PxebcMode->ProxyOfferReceived = *NewProxyOfferReceived;\r
3229 }\r
3230\r
3231 if (NewPxeDiscoverValid != NULL) {\r
3232 PxebcMode->PxeDiscoverValid = *NewPxeDiscoverValid;\r
3233 }\r
3234\r
3235 if (NewPxeReplyReceived != NULL) {\r
3236 PxebcMode->PxeReplyReceived = *NewPxeReplyReceived;\r
3237 }\r
3238\r
3239 if (NewPxeBisReplyReceived != NULL) {\r
3240 PxebcMode->PxeBisReplyReceived = *NewPxeBisReplyReceived;\r
3241 }\r
3242\r
3243 if (NewDhcpDiscover != NULL) {\r
3244 CopyMem (\r
3245 &PxebcMode->DhcpDiscover,\r
3246 NewDhcpDiscover,\r
3247 sizeof *NewDhcpDiscover\r
3248 );\r
3249 }\r
3250\r
3251 if (NewDhcpAck != NULL) {\r
3252 CopyParse (Private, &PxebcMode->DhcpAck, NewDhcpAck, DHCPV4_ACK_INDEX);\r
3253 }\r
3254\r
3255 if (NewProxyOffer != NULL) {\r
3256 CopyParse (Private, &PxebcMode->ProxyOffer, NewProxyOffer, PXE_OFFER_INDEX);\r
3257 }\r
3258\r
3259 if (NewPxeDiscover != NULL) {\r
3260 CopyMem (\r
3261 &PxebcMode->PxeDiscover,\r
3262 NewPxeDiscover,\r
3263 sizeof *NewPxeDiscover\r
3264 );\r
3265 }\r
3266\r
3267 if (NewPxeReply != NULL) {\r
3268 CopyParse (Private, &PxebcMode->PxeReply, NewPxeReply, PXE_ACK_INDEX);\r
3269 }\r
3270\r
3271 if (NewPxeBisReply != NULL) {\r
3272 CopyParse (Private, &PxebcMode->PxeBisReply, NewPxeBisReply, PXE_BIS_INDEX);\r
3273 }\r
3274 //\r
3275 // Unlock the instance data\r
3276 //\r
3277 EfiReleaseLock (&Private->Lock);\r
3278 return EFI_SUCCESS;\r
3279}\r
3280\r
3281/* eof - pxe_bc_dhcp.c */\r