]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/PxeBcDxe/Pxe_bc_dhcp.c
Make MdeModulePkg GCC clean.
[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
476 SMBIOS_STRUCTURE_TABLE *SmbiosTable;\r
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
487 Smbios.Hdr = (SMBIOS_HEADER *) (UINTN) SmbiosTable->TableAddress;\r
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
1424 CopyMem (&DHCPDECLINEoptions.OpDeclineEnd, &DHCP_REQ_OPTIONS, sizeof (struct requestopendstr));\r
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
1732 CopyMem (&DHCP_REQ_OPTIONS, &RequestOpEndStr, sizeof (RequestOpEndStr));\r
1733// DHCP_REQ_OPTIONS = RequestOpEndStr;\r
1734 DHCP_REQ_OPTIONS.OpReqIP.Ip = *(EFI_IPv4_ADDRESS *) &RxBuf[OfferIx].u.Dhcpv4.yiaddr;\r
1735\r
1736 CopyMem (\r
1737 &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip,\r
1738 &((DHCPV4_OP_SERVER_IP *) RxBuf[OfferIx].OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip,\r
1739 sizeof DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip\r
1740 );\r
1741\r
1742 CopyMem (\r
1743 Private->EfiBc.Mode->SubnetMask.Addr,\r
1744 &DefaultSubnetMask,\r
1745 4\r
1746 );\r
1747\r
1748 //\r
1749 // broadcast DHCPREQUEST\r
1750 //\r
1751 if (DoUdpWrite (\r
1752 Private,\r
1753 &BroadcastIP,\r
1754 &DhcpServerPort,\r
1755 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
1756 &DHCPClientPort\r
1757 ) != EFI_SUCCESS) {\r
1758 return FALSE;\r
1759 }\r
1760 //\r
1761 //\r
1762 //\r
1763 StatCode = gBS->CreateEvent (\r
1764 EVT_TIMER,\r
1765 TPL_CALLBACK,\r
1766 NULL,\r
1767 NULL,\r
1768 &TimeoutEvent\r
1769 );\r
1770\r
1771 if (EFI_ERROR (StatCode)) {\r
1772 return FALSE;\r
1773 }\r
1774\r
1775 StatCode = gBS->SetTimer (\r
1776 TimeoutEvent,\r
1777 TimerPeriodic,\r
1778 Private->Timeout * 10000000 + 1000000\r
1779 );\r
1780\r
1781 if (EFI_ERROR (StatCode)) {\r
1782 gBS->CloseEvent (TimeoutEvent);\r
1783 return FALSE;\r
1784 }\r
1785 //\r
1786 // wait for ACK\r
1787 //\r
1788 for (;;) {\r
1789 if (GetOfferAck (\r
1790 Private,\r
1791 DHCPAckEdit,\r
1792 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP,\r
1793 &ServerIp,\r
1794 &DhcpServerPort,\r
1795 &ClientIp,\r
1796 &DHCPClientPort,\r
1797 DhcpRxBuf,\r
1798 TimeoutEvent\r
1799 ) != EFI_SUCCESS) {\r
1800 break;\r
1801 }\r
1802 //\r
1803 // check type of response - need DHCPACK\r
1804 //\r
1805 if (CompareMem (\r
1806 &DHCP_REQ_OPTIONS.OpReqIP.Ip,\r
1807 &DhcpRxBuf->u.Dhcpv4.yiaddr,\r
1808 sizeof (EFI_IPv4_ADDRESS)\r
1809 ) || CompareMem (\r
1810 &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip,\r
1811 &((DHCPV4_OP_SERVER_IP *) DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip,\r
1812 sizeof (EFI_IPv4_ADDRESS)\r
1813 )) {\r
1814 continue;\r
1815 }\r
1816 //\r
1817 // got ACK\r
1818 // check with ARP that IP unused - good return true\r
1819 //\r
1820 if (!SetStationIP (Private)) {\r
1821 //\r
1822 // fail - send DHCPDECLINE and return false\r
1823 //\r
1824 DeclineOffer (Private);\r
1825 break;\r
1826 }\r
1827\r
1828 LocalPtr.OpPtr = DHCPV4_ACK_BUFFER.OpAdds.PktOptAdds[OP_SUBNET_MASK_IX - 1];\r
1829\r
1830 if (LocalPtr.OpPtr != NULL) {\r
1831 CopyMem (\r
1832 (EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->SubnetMask,\r
1833 &LocalPtr.SubnetMaskStr->Ip,\r
1834 sizeof (EFI_IPv4_ADDRESS)\r
1835 );\r
1836 }\r
1837\r
1838 AddRouters (Private, DhcpRxBuf);\r
1839 gBS->CloseEvent (TimeoutEvent);\r
1840 return TRUE;\r
1841 }\r
1842\r
1843 gBS->CloseEvent (TimeoutEvent);\r
1844 return FALSE;\r
1845}\r
1846\r
1847/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1848\r
1849//\r
1850// try a DHCP server of appropriate type\r
1851//\r
1852STATIC\r
1853BOOLEAN\r
1854TryDHCPFinishDORA (\r
1855 PXE_BASECODE_DEVICE *Private,\r
1856 INTN TypeIx\r
1857 )\r
1858{\r
1859 INTN Index;\r
1860\r
1861 //\r
1862 // go through the DHCP servers of the requested type\r
1863 //\r
1864 for (Index = 0; Index < Private->ServerCount[TypeIx]; ++Index) {\r
1865 if (TryFinishDORA (Private, Index = Private->OfferCount[TypeIx][Index])) {\r
1866 if (TypeIx == BINL_IX && !TryFinishBINL (Private, Index)) {\r
1867 continue;\r
1868 }\r
1869\r
1870 return TRUE;\r
1871 }\r
1872 }\r
1873\r
1874 return FALSE;\r
1875}\r
1876\r
1877/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1878\r
1879//\r
1880// try a DHCP only server and a proxy of appropriate type\r
1881//\r
1882STATIC\r
1883BOOLEAN\r
1884TryProxyFinishDORA (\r
1885 PXE_BASECODE_DEVICE *Private,\r
1886 INTN TypeIx\r
1887 )\r
1888{\r
1889 INTN Index;\r
1890\r
1891 if (!Private->GotProxy[TypeIx]) {\r
1892 //\r
1893 // no proxies of the type wanted\r
1894 //\r
1895 return FALSE;\r
1896 }\r
1897 //\r
1898 // go through the DHCP only servers\r
1899 //\r
1900 for (Index = 0; Index < Private->ServerCount[DHCP_ONLY_IX]; ++Index) {\r
1901 if (TryFinishDORA (Private, Private->OfferCount[DHCP_ONLY_IX][Index])) {\r
1902 if (TypeIx != BINL_IX) {\r
1903 CopyProxyRxBuf (Private, Private->GotProxy[TypeIx] - 1);\r
1904 } else if (!TryFinishProxyBINL (Private)) {\r
1905 //\r
1906 // if didn't work with this DHCP, won't work with any\r
1907 //\r
1908 return FALSE;\r
1909 }\r
1910\r
1911 return TRUE;\r
1912 }\r
1913 }\r
1914\r
1915 return FALSE;\r
1916}\r
1917\r
1918/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1919\r
1920//\r
1921// getting to the bottom of the barrel\r
1922//\r
1923STATIC\r
1924BOOLEAN\r
1925TryAnyWithBootfileFinishDORA (\r
1926 PXE_BASECODE_DEVICE *Private\r
1927 )\r
1928{\r
1929 //\r
1930 // try a DHCP only server who has a bootfile\r
1931 //\r
1932 UNION_PTR LocalPtr;\r
1933 INTN Index;\r
1934\r
1935 for (Index = 0; Index < Private->ServerCount[DHCP_ONLY_IX]; ++Index) {\r
1936 INTN offer;\r
1937\r
1938 offer = Private->OfferCount[DHCP_ONLY_IX][Index];\r
1939\r
1940 if (RxBuf[offer].OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] && TryFinishDORA (Private, offer)) {\r
1941 return TRUE;\r
1942 }\r
1943 }\r
1944 //\r
1945 // really at bottom - see if be have any bootps\r
1946 //\r
1947 if (!Private->GotBootp) {\r
1948 return FALSE;\r
1949 }\r
1950\r
1951 DHCP_REQ_OPTIONS.OpReqIP.Ip = *(EFI_IPv4_ADDRESS *) &RxBuf[Private->GotBootp - 1].u.Dhcpv4.yiaddr;\r
1952\r
1953 if (!SetStationIP (Private)) {\r
1954 return FALSE;\r
1955 }\r
1956 //\r
1957 // treat BOOTP response as DHCP ACK packet\r
1958 //\r
1959 CopyParseRxBuf (Private, Private->GotBootp - 1, DHCPV4_ACK_INDEX);\r
1960\r
1961 LocalPtr.OpPtr = RxBuf[Private->GotBootp - 1].OpAdds.PktOptAdds[OP_SUBNET_MASK_IX - 1];\r
1962\r
1963 if (LocalPtr.OpPtr != NULL) {\r
1964 *(EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->SubnetMask = LocalPtr.SubnetMaskStr->Ip;\r
1965 }\r
1966\r
1967 return TRUE;\r
1968}\r
1969\r
1970/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
1971\r
1972/* DoDhcpDora()\r
1973 */\r
1974STATIC\r
1975EFI_STATUS\r
1976DoDhcpDora (\r
1977 PXE_BASECODE_DEVICE *Private,\r
1978 BOOLEAN SortOffers\r
1979 )\r
1980{\r
1981 EFI_PXE_BASE_CODE_IP_FILTER Filter;\r
1982 EFI_STATUS StatCode;\r
1983 INTN NumOffers;\r
1984\r
1985 Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP | EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST;\r
1986\r
1987 Filter.IpCnt = 0;\r
1988 Filter.reserved = 0;\r
1989\r
1990 //\r
1991 // set filter unicast or broadcast\r
1992 //\r
1993 if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) {\r
1994 return StatCode;\r
1995 }\r
1996 //\r
1997 // seed random number with hardware address\r
1998 //\r
1999 SeedRandom (Private, *(UINT16 *) &Private->SimpleNetwork->Mode->CurrentAddress);\r
2000\r
2001 for (Private->Timeout = 1;\r
2002 Private->Timeout < 17;\r
2003 Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), Private->Timeout <<= 1\r
2004 ) {\r
2005 INTN Index;\r
2006\r
2007 InitDhcpv4TxBuf (Private);\r
2008 DHCPV4_TRANSMIT_BUFFER.xid = Random (Private);\r
2009 DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds);\r
2010\r
2011 //\r
2012 // broadcast DHCPDISCOVER\r
2013 //\r
2014 StatCode = DoUdpWrite (\r
2015 Private,\r
2016 &BroadcastIP,\r
2017 &DhcpServerPort,\r
2018 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2019 &DHCPClientPort\r
2020 );\r
2021\r
2022 if (StatCode != EFI_SUCCESS) {\r
2023 return StatCode;\r
2024 }\r
2025\r
2026 CopyMem (\r
2027 &Private->EfiBc.Mode->DhcpDiscover,\r
2028 (EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER,\r
2029 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2030 );\r
2031\r
2032 //\r
2033 // get DHCPOFFER's\r
2034 //\r
2035 if ((StatCode = GetOffers (Private)) != EFI_SUCCESS) {\r
2036 if (StatCode != EFI_NO_RESPONSE) {\r
2037 return StatCode;\r
2038 }\r
2039\r
2040 continue;\r
2041 }\r
2042 //\r
2043 // select offer and reply DHCPREQUEST\r
2044 //\r
2045 if (SortOffers) {\r
2046 if (TryDHCPFinishDORA(Private, PXE10_IX) || // try DHCP with PXE10\r
2047 TryDHCPFinishDORA(Private, WfM11a_IX) || // no - try with WfM\r
2048 TryProxyFinishDORA(Private, PXE10_IX) || // no - try DHCP only and proxy with PXE10\r
2049 TryProxyFinishDORA(Private, WfM11a_IX) || // no - try DHCP only and proxy with WfM\r
2050 TryDHCPFinishDORA(Private, BINL_IX) || // no - try with WfM\r
2051 TryProxyFinishDORA(Private, BINL_IX) || // no - try DHCP only and proxy with PXE10\r
2052 TryAnyWithBootfileFinishDORA(Private))\r
2053 {\r
2054 return EFI_SUCCESS;\r
2055 }\r
2056\r
2057 continue;\r
2058 }\r
2059 //\r
2060 // FIFO order\r
2061 //\r
2062 NumOffers = Private->NumOffersReceived;\r
2063\r
2064 for (Index = 0; Index < NumOffers; ++Index) {\r
2065 //\r
2066 // ignore proxies\r
2067 //\r
2068 if (!RxBuf[Index].u.Dhcpv4.yiaddr) {\r
2069 continue;\r
2070 }\r
2071 //\r
2072 // check if a bootp server\r
2073 //\r
2074 if (!RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1]) {\r
2075 //\r
2076 // it is - just check ARP\r
2077 //\r
2078 if (!SetStationIP (Private)) {\r
2079 continue;\r
2080 }\r
2081 }\r
2082 //\r
2083 // else check if a DHCP only server\r
2084 //\r
2085 else if (!(RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE | PXE_TYPE))) {\r
2086 //\r
2087 // it is a normal DHCP offer (without any PXE options), just finish the D.O.R.A by sending DHCP request.\r
2088 //\r
2089 if (!TryFinishDORA (Private, Index)) {\r
2090 continue;\r
2091 }\r
2092 } else if (TryFinishDORA (Private, Index)) {\r
2093 if (!(RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE)) && !TryFinishBINL (Private, Index)) {\r
2094 continue;\r
2095 }\r
2096 }\r
2097\r
2098 DEBUG ((DEBUG_WARN, "\nDoDhcpDora() Got packets. "));\r
2099 return EFI_SUCCESS;\r
2100 }\r
2101 //\r
2102 // now look for DHCP onlys and a Proxy\r
2103 //\r
2104 for (Index = 0; Index < NumOffers; ++Index) {\r
2105 INT8 Index2;\r
2106\r
2107 //\r
2108 // ignore proxies, bootps, non DHCP onlys, and bootable DHCPS\r
2109 //\r
2110 if (!RxBuf[Index].u.Dhcpv4.yiaddr ||\r
2111 !RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1] ||\r
2112 RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE | PXE_TYPE) ||\r
2113 RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]\r
2114 ) {\r
2115 continue;\r
2116 }\r
2117 //\r
2118 // found non bootable DHCP only - try to find a proxy\r
2119 //\r
2120 for (Index2 = 0; Index2 < NumOffers; ++Index2) {\r
2121 if (!RxBuf[Index2].u.Dhcpv4.yiaddr) {\r
2122 if (!TryFinishDORA (Private, Index)) {\r
2123 //\r
2124 // DHCP no ACK\r
2125 //\r
2126 break;\r
2127 }\r
2128\r
2129 if (RxBuf[Index2].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE)) {\r
2130 CopyProxyRxBuf (Private, Index2);\r
2131 } else if (!TryFinishBINL (Private, Index2)) {\r
2132 continue;\r
2133 }\r
2134\r
2135 DEBUG ((DEBUG_WARN, "\nDoDhcpDora() Got packets. "));\r
2136 return EFI_SUCCESS;\r
2137 }\r
2138 }\r
2139 }\r
2140 }\r
2141\r
2142 return EFI_NO_RESPONSE;\r
2143}\r
2144\r
2145/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2146\r
2147//\r
2148// determine if the server ip is in the ip list\r
2149//\r
2150BOOLEAN\r
2151InServerList (\r
2152 EFI_IP_ADDRESS *ServerIpPtr,\r
2153 PXE_SERVER_LISTS *ServerListPtr\r
2154 )\r
2155{\r
2156 UINTN Index;\r
2157\r
2158 if (!ServerListPtr || !ServerListPtr->Ipv4List.IpCount) {\r
2159 return TRUE;\r
2160 }\r
2161\r
2162 for (Index = 0; Index < ServerListPtr->Ipv4List.IpCount; ++Index) {\r
2163 if (!CompareMem (\r
2164 ServerIpPtr,\r
2165 &ServerListPtr->Ipv4List.IpList[Index],\r
2166 sizeof (EFI_IPv4_ADDRESS)\r
2167 )) {\r
2168 return TRUE;\r
2169 }\r
2170 }\r
2171\r
2172 return FALSE;\r
2173}\r
2174\r
2175/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2176BOOLEAN\r
2177ExtractBootServerList (\r
2178 UINT16 Type,\r
2179 DHCPV4_OP_STRUCT *ptr,\r
2180 PXE_SERVER_LISTS **ServerListPtr\r
2181 )\r
2182{\r
2183 UNION_PTR LocalPtr;\r
2184 INTN ServerListLen;\r
2185\r
2186 LocalPtr.OpPtr = ptr;\r
2187 ServerListLen = LocalPtr.BootServersStr->Header.Length;\r
2188\r
2189 //\r
2190 // find type\r
2191 //\r
2192 LocalPtr.BootServerList = LocalPtr.BootServersStr->ServerList;\r
2193\r
2194 while (ServerListLen) {\r
2195 INTN ServerEntryLen;\r
2196\r
2197 ServerEntryLen = sizeof (PXEV4_SERVER_LIST) + 2 + (LocalPtr.BootServerList->u.Ipv4List.IpCount - 1) *\r
2198 sizeof (EFI_IPv4_ADDRESS);\r
2199\r
2200 if (NTOHS (LocalPtr.BootServerList->Type) == Type) {\r
2201 *ServerListPtr = &LocalPtr.BootServerList->u;\r
2202 return TRUE;\r
2203 }\r
2204\r
2205 (LocalPtr.BytePtr) += ServerEntryLen;\r
2206 ServerListLen -= ServerEntryLen;\r
2207 }\r
2208\r
2209 return FALSE;\r
2210}\r
2211\r
2212/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2213VOID\r
2214FreeMem (\r
2215 PXE_BASECODE_DEVICE *Private\r
2216 )\r
2217{\r
2218 if (Private->TransmitBuffer != NULL) {\r
2219 gBS->FreePool (Private->TransmitBuffer);\r
2220 Private->TransmitBuffer = NULL;\r
2221 }\r
2222\r
2223 if (Private->ReceiveBuffers != NULL) {\r
2224 gBS->FreePool (Private->ReceiveBuffers);\r
2225 Private->ReceiveBuffers = NULL;\r
2226 }\r
2227}\r
2228\r
2229/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2230BOOLEAN\r
2231GetMem (\r
2232 PXE_BASECODE_DEVICE *Private\r
2233 )\r
2234{\r
2235 EFI_STATUS Status;\r
2236\r
2237 if (Private->DhcpPacketBuffer == NULL) {\r
2238 Status = gBS->AllocatePool (\r
2239 EfiBootServicesData,\r
2240 sizeof (DHCP_RECEIVE_BUFFER) * (PXE_BIS_INDEX + 1),\r
2241 &Private->DhcpPacketBuffer\r
2242 );\r
2243\r
2244 if (EFI_ERROR (Status) || Private->DhcpPacketBuffer == NULL) {\r
2245 Private->DhcpPacketBuffer = NULL;\r
2246 FreeMem (Private);\r
2247 return FALSE;\r
2248 }\r
2249 }\r
2250\r
2251 Status = gBS->AllocatePool (\r
2252 EfiBootServicesData,\r
2253 sizeof (EFI_PXE_BASE_CODE_PACKET),\r
2254 &Private->TransmitBuffer\r
2255 );\r
2256\r
2257 if (EFI_ERROR (Status) || Private->TransmitBuffer == NULL) {\r
2258 gBS->FreePool (Private->DhcpPacketBuffer);\r
2259 Private->DhcpPacketBuffer = NULL;\r
2260 Private->TransmitBuffer = NULL;\r
2261 FreeMem (Private);\r
2262 return FALSE;\r
2263 }\r
2264\r
2265 Status = gBS->AllocatePool (\r
2266 EfiBootServicesData,\r
2267 sizeof (DHCP_RECEIVE_BUFFER) * (MAX_OFFERS),\r
2268 &Private->ReceiveBuffers\r
2269 );\r
2270\r
2271 if (EFI_ERROR (Status) || Private->ReceiveBuffers == NULL) {\r
2272 gBS->FreePool (Private->TransmitBuffer);\r
2273 gBS->FreePool (Private->DhcpPacketBuffer);\r
2274 Private->DhcpPacketBuffer = NULL;\r
2275 Private->TransmitBuffer = NULL;\r
2276 Private->ReceiveBuffers = NULL;\r
2277 FreeMem (Private);\r
2278 return FALSE;\r
2279 }\r
2280\r
2281 return TRUE;\r
2282}\r
2283\r
2284/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2285\r
2286/**\r
2287\r
2288\r
2289**/\r
2290EFI_STATUS\r
2291EFIAPI\r
2292BcDhcp (\r
2293 IN EFI_PXE_BASE_CODE_PROTOCOL *This,\r
2294 IN BOOLEAN SortOffers\r
2295 )\r
2296{\r
2297 EFI_PXE_BASE_CODE_IP_FILTER Filter;\r
2298 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
2299 PXE_BASECODE_DEVICE *Private;\r
2300 EFI_STATUS StatCode;\r
2301\r
2302 //\r
2303 // Lock the instance data and make sure started\r
2304 //\r
2305 StatCode = EFI_SUCCESS;\r
2306\r
2307 if (This == NULL) {\r
2308 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
2309 return EFI_INVALID_PARAMETER;\r
2310 }\r
2311\r
2312 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
2313\r
2314 if (Private == NULL) {\r
2315 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE pointer == NULL"));\r
2316 return EFI_INVALID_PARAMETER;\r
2317 }\r
2318\r
2319 EfiAcquireLock (&Private->Lock);\r
2320\r
2321 if (This->Mode == NULL || !This->Mode->Started) {\r
2322 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
2323 EfiReleaseLock (&Private->Lock);\r
2324 return EFI_NOT_STARTED;\r
2325 }\r
2326\r
2327 Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP;\r
2328 Filter.IpCnt = 0;\r
2329 Filter.reserved = 0;\r
2330\r
2331 DEBUG ((DEBUG_INFO, "\nBcDhcp() Enter. "));\r
2332\r
2333 PxebcMode = Private->EfiBc.Mode;\r
2334\r
2335 if (!GetMem (Private)) {\r
2336 DEBUG ((DEBUG_ERROR, "\nBcDhcp() GetMem() failed.\n"));\r
2337 EfiReleaseLock (&Private->Lock);\r
2338 return EFI_OUT_OF_RESOURCES;\r
2339 }\r
2340\r
2341 PxebcMode->DhcpDiscoverValid = FALSE;\r
2342 PxebcMode->DhcpAckReceived = FALSE;\r
2343 PxebcMode->ProxyOfferReceived = FALSE;\r
2344\r
2345 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DHCP;\r
2346\r
2347 //\r
2348 // Issue BC command\r
2349 //\r
2350 if (Private->TotalSeconds == 0) {\r
2351 //\r
2352 // put in seconds field of DHCP send packets\r
2353 //\r
2354 Private->TotalSeconds = 4;\r
2355 }\r
2356\r
2357 if ((StatCode = DoDhcpDora (Private, SortOffers)) == EFI_SUCCESS) {\r
2358 //\r
2359 // success - copy packets\r
2360 //\r
2361 PxebcMode->DhcpDiscoverValid = PxebcMode->DhcpAckReceived = TRUE;\r
2362\r
2363 CopyMem (\r
2364 &PxebcMode->DhcpAck,\r
2365 (EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_ACK_PACKET,\r
2366 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2367 );\r
2368\r
2369 if (PxebcMode->ProxyOfferReceived) {\r
2370 CopyMem (\r
2371 &PxebcMode->ProxyOffer,\r
2372 (EFI_PXE_BASE_CODE_PACKET *) &PXE_OFFER_PACKET,\r
2373 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2374 );\r
2375 }\r
2376 }\r
2377 //\r
2378 // set filter back to unicast\r
2379 //\r
2380 IpFilter (Private, &Filter);\r
2381\r
2382 FreeMem (Private);\r
2383\r
2384 //\r
2385 // Unlock the instance data\r
2386 //\r
2387 DEBUG ((DEBUG_WARN, "\nBcDhcp() Exit = %xh ", StatCode));\r
2388\r
2389 EfiReleaseLock (&Private->Lock);\r
2390 return StatCode;\r
2391}\r
2392\r
2393/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2394STATIC\r
2395BOOLEAN\r
2396VerifyCredentialOption (\r
2397 UINT8 *tx,\r
2398 UINT8 *rx\r
2399 )\r
2400{\r
2401 UINTN n;\r
2402\r
2403 //\r
2404 // Fail verification if either pointer is NULL.\r
2405 //\r
2406 if (tx == NULL || rx == NULL) {\r
2407 return FALSE;\r
2408 }\r
2409 //\r
2410 // Fail verification if tx[0] is not a credential type option\r
2411 // or if the length is zero or not a multiple of four.\r
2412 //\r
2413 if (tx[0] != VEND_PXE_CREDENTIAL_TYPES || tx[1] == 0 || tx[1] % 4 != 0) {\r
2414 return FALSE;\r
2415 }\r
2416 //\r
2417 // Fail verification if rx[0] is not a credential type option\r
2418 // or if the length is not equal to four.\r
2419 //\r
2420 if (rx[0] != VEND_PXE_CREDENTIAL_TYPES || rx[1] != 4) {\r
2421 return FALSE;\r
2422 }\r
2423 //\r
2424 // Look through transmitted credential types for a copy\r
2425 // of the received credential type.\r
2426 //\r
2427 for (n = 0; n < tx[1]; n += 4) {\r
2428 if (!CompareMem (&tx[n + 2], &rx[2], 4)) {\r
2429 return TRUE;\r
2430 }\r
2431 }\r
2432\r
2433 return FALSE;\r
2434}\r
2435\r
2436/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2437\r
2438/**\r
2439\r
2440\r
2441**/\r
2442EFI_STATUS\r
2443DoDiscover (\r
2444 PXE_BASECODE_DEVICE *Private,\r
2445 UINT16 OpFlags,\r
2446 IN UINT16 Type,\r
2447 IN UINT16 *LayerPtr,\r
2448 IN BOOLEAN UseBis,\r
2449 EFI_IP_ADDRESS *DestPtr,\r
2450 PXE_SERVER_LISTS *ServerListPtr\r
2451 )\r
2452{\r
2453 EFI_PXE_BASE_CODE_UDP_PORT ClientPort;\r
2454 EFI_PXE_BASE_CODE_UDP_PORT ServerPort;\r
2455 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
2456 EFI_STATUS StatCode;\r
2457 EFI_EVENT TimeoutEvent;\r
2458 UINT8 OpLen;\r
2459\r
2460 PxebcMode = Private->EfiBc.Mode;\r
2461\r
2462 if (DestPtr->Addr[0] == 0) {\r
2463 DEBUG ((DEBUG_WARN, "\nDoDiscover() !DestPtr->Addr[0]"));\r
2464 return EFI_INVALID_PARAMETER;\r
2465 }\r
2466 //\r
2467 // seed random number with hardware address\r
2468 //\r
2469 SeedRandom (Private, *(UINT16 *) &Private->SimpleNetwork->Mode->CurrentAddress);\r
2470\r
2471 if (DestPtr->Addr[0] == BroadcastIP.Addr[0]) {\r
2472 ClientPort = DHCPClientPort;\r
2473 ServerPort = DhcpServerPort;\r
2474 } else {\r
2475 ClientPort = PSEUDO_DHCP_CLIENT_PORT;\r
2476 ServerPort = PseudoDhcpServerPort;\r
2477 }\r
2478\r
2479 if (UseBis) {\r
2480 *LayerPtr |= PXE_BOOT_LAYER_CREDENTIAL_FLAG;\r
2481 } else {\r
2482 *LayerPtr &= PXE_BOOT_LAYER_MASK;\r
2483 }\r
2484\r
2485 for (Private->Timeout = 1;\r
2486 Private->Timeout < 5;\r
2487 Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), ++Private->Timeout\r
2488 ) {\r
2489 InitDhcpv4TxBuf (Private);\r
2490 //\r
2491 // initialize DHCP message structure\r
2492 //\r
2493 DHCPV4_TRANSMIT_BUFFER.xid = Random (Private);\r
2494 DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds);\r
2495 CopyMem (\r
2496 &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2497 &PxebcMode->StationIp,\r
2498 sizeof DHCPV4_TRANSMIT_BUFFER.ciaddr\r
2499 );\r
2500\r
2501 DHCPV4_OPTIONS_BUFFER.DhcpMessageType.Type = DHCPREQUEST;\r
2502 DISCOVERoptions.Header.OpCode = OP_VENDOR_SPECIFIC;\r
2503 DISCOVERoptions.BootItem.Header.OpCode = VEND_PXE_BOOT_ITEM;\r
2504 DISCOVERoptions.BootItem.Header.Length = DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM);\r
2505 DISCOVERoptions.BootItem.Type = HTONS (Type);\r
2506 DISCOVERoptions.BootItem.Layer = HTONS (*LayerPtr);\r
2507\r
2508 if (UseBis) {\r
2509 EFI_BIS_PROTOCOL *BisPtr;\r
2510 BIS_APPLICATION_HANDLE BisAppHandle;\r
2511 EFI_BIS_DATA *BisDataSigInfo;\r
2512 EFI_BIS_SIGNATURE_INFO *BisSigInfo;\r
2513 UINTN Index;\r
2514 UINTN Index2;\r
2515\r
2516 BisPtr = PxebcBisStart (\r
2517 Private,\r
2518 &BisAppHandle,\r
2519 &BisDataSigInfo\r
2520 );\r
2521\r
2522 if (BisPtr == NULL) {\r
2523 //\r
2524 // %%TBD - In order to get here, BIS must have\r
2525 // been present when PXEBC.Start() was called.\r
2526 // BIS had to be shutdown/removed/damaged\r
2527 // before PXEBC.Discover() was called.\r
2528 // Do we need to document a specific error\r
2529 // for this case?\r
2530 //\r
2531 return EFI_OUT_OF_RESOURCES;\r
2532 }\r
2533 //\r
2534 // Compute number of credential types.\r
2535 //\r
2536 Index2 = BisDataSigInfo->Length / sizeof (EFI_BIS_SIGNATURE_INFO);\r
2537\r
2538 DISCREDoptions.Header.OpCode = VEND_PXE_CREDENTIAL_TYPES;\r
2539\r
2540 DISCREDoptions.Header.Length = (UINT8) (Index2 * sizeof (PXE_CREDENTIAL));\r
2541\r
2542 OpLen = (UINT8) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS) + sizeof (DHCPV4_OP_HEADER) + DISCREDoptions.Header.Length);\r
2543\r
2544 BisSigInfo = (EFI_BIS_SIGNATURE_INFO *) BisDataSigInfo->Data;\r
2545\r
2546 for (Index = 0; Index < Index2; ++Index) {\r
2547 UINT32 x;\r
2548\r
2549 CopyMem (&x, &BisSigInfo[Index], sizeof x);\r
2550 x = HTONL (x);\r
2551 CopyMem (&DISCREDoptions.Credentials[Index], &x, sizeof x);\r
2552 }\r
2553\r
2554 PxebcBisStop (BisPtr, BisAppHandle, BisDataSigInfo);\r
2555 } else {\r
2556 OpLen = DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS);\r
2557 }\r
2558\r
2559 DISCOVERoptions.Header.Length = OpLen;\r
2560\r
2561 ((UINT8 *) &DISCOVERoptions)[sizeof (DHCPV4_OP_HEADER) + OpLen - 1] = OP_END;\r
2562 ((UINT8 *) &DISCOVERoptions)[sizeof (DHCPV4_OP_HEADER) + OpLen] = OP_END;\r
2563\r
2564 StatCode = DoUdpWrite (\r
2565 Private,\r
2566 DestPtr,\r
2567 &ServerPort,\r
2568 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2569 &ClientPort\r
2570 );\r
2571\r
2572 if (StatCode != EFI_SUCCESS) {\r
2573 return StatCode;\r
2574 }\r
2575 //\r
2576 //\r
2577 //\r
2578 StatCode = gBS->CreateEvent (\r
2579 EVT_TIMER,\r
2580 TPL_CALLBACK,\r
2581 NULL,\r
2582 NULL,\r
2583 &TimeoutEvent\r
2584 );\r
2585\r
2586 if (EFI_ERROR (StatCode)) {\r
2587 return StatCode;\r
2588 }\r
2589\r
2590 StatCode = gBS->SetTimer (\r
2591 TimeoutEvent,\r
2592 TimerRelative,\r
2593 Private->Timeout * 10000000 + 1000000\r
2594 );\r
2595\r
2596 if (EFI_ERROR (StatCode)) {\r
2597 gBS->CloseEvent (TimeoutEvent);\r
2598 return StatCode;\r
2599 }\r
2600 //\r
2601 // wait for ACK\r
2602 //\r
2603 for (;;) {\r
2604 DHCP_RECEIVE_BUFFER *RxBufPtr;\r
2605 UINT16 TmpType;\r
2606 UINT16 TmpLayer;\r
2607\r
2608 RxBufPtr = UseBis ? &PXE_BIS_BUFFER : &PXE_ACK_BUFFER;\r
2609 ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS));\r
2610\r
2611 if (GetOfferAck (\r
2612 Private,\r
2613 AckEdit,\r
2614 OpFlags,\r
2615 (EFI_IP_ADDRESS *) &Private->ServerIp,\r
2616 0,\r
2617 (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr,\r
2618 &ClientPort,\r
2619 RxBufPtr,\r
2620 TimeoutEvent\r
2621 ) != EFI_SUCCESS) {\r
2622 break;\r
2623 }\r
2624 //\r
2625 // check type of response - need PXEClient DHCPACK of proper type with bootfile\r
2626 //\r
2627 if (!(RxBufPtr->OpAdds.Status & PXE_TYPE) ||\r
2628 (UseBis && (RxBufPtr->OpAdds.Status & USE_THREE_BYTE)) ||\r
2629 !RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] ||\r
2630 !RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1] ||\r
2631 !InServerList((EFI_IP_ADDRESS *)&((DHCPV4_OP_SERVER_IP *)RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX-1])->Ip, ServerListPtr)) {\r
2632\r
2633 continue;\r
2634 }\r
2635\r
2636 TmpType = TmpLayer = 0;\r
2637\r
2638 if (RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1]) {\r
2639 TmpType = NTOHS (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Type);\r
2640\r
2641 if (RxBufPtr->OpAdds.Status & USE_THREE_BYTE) {\r
2642 TmpLayer = (UINT16) (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Layer >> 8);\r
2643 } else {\r
2644 TmpLayer = NTOHS (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Layer);\r
2645 }\r
2646 }\r
2647\r
2648 if (TmpType != Type) {\r
2649 continue;\r
2650 }\r
2651\r
2652 if (UseBis) {\r
2653 if (!RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_CREDENTIAL_TYPES_IX - 1]) {\r
2654 continue;\r
2655 }\r
2656\r
2657 if (!VerifyCredentialOption (\r
2658 (UINT8 *) &DISCREDoptions.Header,\r
2659 (UINT8 *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_CREDENTIAL_TYPES_IX - 1]\r
2660 )) {\r
2661 continue;\r
2662 }\r
2663 }\r
2664\r
2665 *LayerPtr = TmpLayer;\r
2666\r
2667 if (UseBis) {\r
2668 CopyMem (\r
2669 &PxebcMode->PxeBisReply,\r
2670 &RxBufPtr->u.Dhcpv4,\r
2671 sizeof (EFI_PXE_BASE_CODE_PACKET)\r
2672 );\r
2673\r
2674 PxebcMode->PxeBisReplyReceived = TRUE;\r
2675\r
2676 StatCode = DoDiscover (\r
2677 Private,\r
2678 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2679 Type,\r
2680 LayerPtr,\r
2681 FALSE,\r
2682 &Private->ServerIp,\r
2683 0\r
2684 );\r
2685\r
2686 gBS->CloseEvent (TimeoutEvent);\r
2687 return StatCode;\r
2688 }\r
2689\r
2690 PxebcMode->PxeDiscoverValid = PxebcMode->PxeReplyReceived = TRUE;\r
2691\r
2692 CopyMem (\r
2693 &PxebcMode->PxeDiscover,\r
2694 &*(EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER,\r
2695 sizeof (*(EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER)\r
2696 );\r
2697\r
2698 CopyMem (\r
2699 &PxebcMode->PxeReply,\r
2700 &*(EFI_PXE_BASE_CODE_PACKET *) &RxBufPtr->u.Dhcpv4,\r
2701 sizeof (*(EFI_PXE_BASE_CODE_PACKET *) &RxBufPtr->u.Dhcpv4)\r
2702 );\r
2703\r
2704 AddRouters (Private, RxBufPtr);\r
2705\r
2706 gBS->CloseEvent (TimeoutEvent);\r
2707 return EFI_SUCCESS;\r
2708 }\r
2709\r
2710 gBS->CloseEvent (TimeoutEvent);\r
2711 }\r
2712 //\r
2713 // end for loop\r
2714 //\r
2715 return EFI_TIMEOUT;\r
2716}\r
2717\r
2718/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2719\r
2720/**\r
2721 Parameters:\r
2722 Private := Pointer to PxeBc interface\r
2723 Type :=\r
2724 LayerPtr :=\r
2725 UseBis :=\r
2726 DiscoverInfoPtr :=\r
2727 McastServerListPtr :=\r
2728 ServerListPtr :=\r
2729\r
2730\r
2731**/\r
2732STATIC\r
2733EFI_STATUS\r
2734Discover (\r
2735 PXE_BASECODE_DEVICE *Private,\r
2736 IN UINT16 Type,\r
2737 IN UINT16 *LayerPtr,\r
2738 IN BOOLEAN UseBis,\r
2739 IN EFI_PXE_BASE_CODE_DISCOVER_INFO *DiscoverInfoPtr,\r
2740 PXE_SERVER_LISTS *McastServerListPtr,\r
2741 PXE_SERVER_LISTS *ServerListPtr\r
2742 )\r
2743{\r
2744 EFI_IP_ADDRESS DestIp;\r
2745 EFI_STATUS StatCode;\r
2746\r
2747 DEBUG ((DEBUG_INFO, "\nDiscover() Type=%d Layer=%d ", Type, *LayerPtr));\r
2748\r
2749 if (UseBis) {\r
2750 DEBUG ((DEBUG_INFO, "BIS "));\r
2751 }\r
2752 //\r
2753 // get dest IP addr - mcast, bcast, or unicast\r
2754 //\r
2755 if (DiscoverInfoPtr->UseMCast) {\r
2756 DestIp.v4 = DiscoverInfoPtr->ServerMCastIp.v4;\r
2757\r
2758 DEBUG (\r
2759 (DEBUG_INFO,\r
2760 "\nDiscover() MCast %d.%d.%d.%d ",\r
2761 DestIp.v4.Addr[0],\r
2762 DestIp.v4.Addr[1],\r
2763 DestIp.v4.Addr[2],\r
2764 DestIp.v4.Addr[3])\r
2765 );\r
2766\r
2767 if ((StatCode = DoDiscover (\r
2768 Private,\r
2769 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2770 Type,\r
2771 LayerPtr,\r
2772 UseBis,\r
2773 &DestIp,\r
2774 McastServerListPtr\r
2775 )) != EFI_TIMEOUT) {\r
2776 DEBUG (\r
2777 (DEBUG_WARN,\r
2778 "\nDiscover() status == %r (%Xh)",\r
2779 StatCode,\r
2780 StatCode)\r
2781 );\r
2782\r
2783 return StatCode;\r
2784 }\r
2785 }\r
2786\r
2787 if (DiscoverInfoPtr->UseBCast) {\r
2788 DEBUG ((DEBUG_INFO, "\nDiscver() BCast "));\r
2789\r
2790 if ((StatCode = DoDiscover (\r
2791 Private,\r
2792 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2793 Type,\r
2794 LayerPtr,\r
2795 UseBis,\r
2796 &BroadcastIP,\r
2797 McastServerListPtr\r
2798 )) != EFI_TIMEOUT) {\r
2799\r
2800 DEBUG ((DEBUG_WARN, "\nDiscover() status == %r (%Xh)", StatCode, StatCode));\r
2801\r
2802 return StatCode;\r
2803 }\r
2804 }\r
2805\r
2806 if (DiscoverInfoPtr->UseUCast) {\r
2807 UINTN Index;\r
2808\r
2809 DEBUG (\r
2810 (DEBUG_INFO,\r
2811 "\nDiscover() UCast IP#=%d ",\r
2812 ServerListPtr->Ipv4List.IpCount)\r
2813 );\r
2814\r
2815 for (Index = 0; Index < ServerListPtr->Ipv4List.IpCount; ++Index) {\r
2816 CopyMem (&DestIp, &ServerListPtr->Ipv4List.IpList[Index], 4);\r
2817\r
2818 DEBUG (\r
2819 (DEBUG_INFO,\r
2820 "\nDiscover() UCast %d.%d.%d.%d ",\r
2821 DestIp.v4.Addr[0],\r
2822 DestIp.v4.Addr[1],\r
2823 DestIp.v4.Addr[2],\r
2824 DestIp.v4.Addr[3])\r
2825 );\r
2826\r
2827 if ((StatCode = DoDiscover (\r
2828 Private,\r
2829 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT,\r
2830 Type,\r
2831 LayerPtr,\r
2832 UseBis,\r
2833 &DestIp,\r
2834 0\r
2835 )) != EFI_TIMEOUT) {\r
2836 DEBUG (\r
2837 (DEBUG_WARN,\r
2838 "\nDiscover() status == %r (%Xh)",\r
2839 StatCode,\r
2840 StatCode)\r
2841 );\r
2842\r
2843 return StatCode;\r
2844 }\r
2845 }\r
2846 }\r
2847\r
2848 DEBUG ((DEBUG_WARN, "\nDiscover() TIMEOUT"));\r
2849\r
2850 return EFI_TIMEOUT;\r
2851}\r
2852\r
2853/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
2854\r
2855/* BcDiscover()\r
2856 */\r
2857\r
2858/**\r
2859\r
2860\r
2861**/\r
2862EFI_STATUS\r
2863EFIAPI\r
2864BcDiscover (\r
2865 IN EFI_PXE_BASE_CODE_PROTOCOL * This,\r
2866 IN UINT16 Type,\r
2867 IN UINT16 *LayerPtr,\r
2868 IN BOOLEAN UseBis,\r
2869 IN EFI_PXE_BASE_CODE_DISCOVER_INFO * DiscoverInfoPtr OPTIONAL\r
2870 )\r
2871{\r
2872 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo;\r
2873 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
2874 DHCP_RECEIVE_BUFFER *DhcpRxBuf;\r
2875 PXE_SERVER_LISTS DefaultSrvList;\r
2876 PXE_SERVER_LISTS *ServerListPtr;\r
2877 PXE_SERVER_LISTS *McastServerListPtr;\r
2878 UNION_PTR LocalPtr;\r
2879 UINTN Index;\r
2880 UINTN Index2;\r
2881 BOOLEAN AcquiredSrvList;\r
2882 EFI_STATUS StatCode;\r
2883 PXE_BASECODE_DEVICE *Private;\r
2884\r
2885 //\r
2886 // Lock the instance data and make sure started\r
2887 //\r
2888 StatCode = EFI_SUCCESS;\r
2889\r
2890 if (This == NULL) {\r
2891 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
2892 return EFI_INVALID_PARAMETER;\r
2893 }\r
2894\r
2895 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
2896\r
2897 if (Private == NULL) {\r
2898 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
2899 return EFI_INVALID_PARAMETER;\r
2900 }\r
2901\r
2902 EfiAcquireLock (&Private->Lock);\r
2903\r
2904 if (This->Mode == NULL || !This->Mode->Started) {\r
2905 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
2906 EfiReleaseLock (&Private->Lock);\r
2907 return EFI_NOT_STARTED;\r
2908 }\r
2909\r
2910 ServerListPtr = NULL;\r
2911 McastServerListPtr = NULL;\r
2912 AcquiredSrvList = FALSE;\r
2913\r
2914 PxebcMode = Private->EfiBc.Mode;\r
2915\r
2916 if (!GetMem (Private)) {\r
2917 EfiReleaseLock (&Private->Lock);\r
2918 return EFI_OUT_OF_RESOURCES;\r
2919 }\r
2920\r
2921 if (UseBis) {\r
2922 if (!PxebcMode->BisSupported) {\r
2923 EfiReleaseLock (&Private->Lock);\r
2924 return EFI_INVALID_PARAMETER;\r
2925 }\r
2926 }\r
2927\r
2928 Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER;\r
2929\r
2930 if (Private->TotalSeconds == 0) {\r
2931 //\r
2932 // put in seconds field of DHCP send packets\r
2933 //\r
2934 Private->TotalSeconds = 4;\r
2935 }\r
2936\r
2937 ZeroMem (&DefaultInfo, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO));\r
2938\r
2939 //\r
2940 // if layer number not zero, use previous discover\r
2941 //\r
2942 if (*LayerPtr != 0) {\r
2943 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0"));\r
2944\r
2945 if (DiscoverInfoPtr != NULL) {\r
2946 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n"));\r
2947\r
2948 EfiReleaseLock (&Private->Lock);\r
2949 return EFI_INVALID_PARAMETER;\r
2950 }\r
2951\r
2952 if (!PxebcMode->PxeDiscoverValid) {\r
2953 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n"));\r
2954\r
2955 EfiReleaseLock (&Private->Lock);\r
2956 return EFI_INVALID_PARAMETER;\r
2957 }\r
2958\r
2959 if (!PxebcMode->PxeReplyReceived) {\r
2960 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n"));\r
2961\r
2962 EfiReleaseLock (&Private->Lock);\r
2963 return EFI_INVALID_PARAMETER;\r
2964 }\r
2965\r
2966 if (UseBis && !PxebcMode->PxeBisReplyReceived) {\r
2967 DEBUG ((DEBUG_WARN, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n"));\r
2968\r
2969 EfiReleaseLock (&Private->Lock);\r
2970 return EFI_INVALID_PARAMETER;\r
2971 }\r
2972\r
2973 DefaultInfo.UseUCast = TRUE;\r
2974 DiscoverInfoPtr = &DefaultInfo;\r
2975\r
2976 DefaultSrvList.Ipv4List.IpCount = 1;\r
2977 CopyMem (&DefaultSrvList.Ipv4List.IpList[0], &Private->ServerIp, 4);\r
2978\r
2979 ServerListPtr = &DefaultSrvList;\r
2980 }\r
2981 //\r
2982 // layer is zero - see if info is supplied or if we need to use info from a cached offer\r
2983 //\r
2984 else if (!DiscoverInfoPtr) {\r
2985 //\r
2986 // not supplied - generate it\r
2987 // make sure that there is cached, appropriate information\r
2988 // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail\r
2989 //\r
2990 DhcpRxBuf = (PxebcMode->ProxyOfferReceived) ? &PXE_OFFER_BUFFER : &DHCPV4_ACK_BUFFER;\r
2991\r
2992 if (!PxebcMode->DhcpAckReceived || !(DhcpRxBuf->OpAdds.Status & DISCOVER_TYPE)) {\r
2993 DEBUG ((DEBUG_WARN, "\nBcDiscover() !ack && !proxy"));\r
2994 EfiReleaseLock (&Private->Lock);\r
2995 return EFI_INVALID_PARAMETER;\r
2996 }\r
2997\r
2998 DiscoverInfoPtr = &DefaultInfo;\r
2999\r
3000 LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1];\r
3001\r
3002 //\r
3003 // if multicast enabled, need multicast address\r
3004 //\r
3005 if (!(LocalPtr.DiscoveryControl->ControlBits & DISABLE_MCAST)) {\r
3006 DefaultInfo.UseMCast = TRUE;\r
3007\r
3008 CopyMem (\r
3009 ((EFI_IPv4_ADDRESS *) &DefaultInfo.ServerMCastIp),\r
3010 &((DHCPV4_OP_IP_ADDRESS *) DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_MCAST_ADDR_IX - 1])->Ip,\r
3011 sizeof (EFI_IPv4_ADDRESS)\r
3012 );\r
3013 }\r
3014\r
3015 DefaultInfo.UseBCast = (BOOLEAN) ((LocalPtr.DiscoveryControl->ControlBits & DISABLE_BCAST) == 0);\r
3016\r
3017 DefaultInfo.MustUseList = (BOOLEAN) ((LocalPtr.DiscoveryControl->ControlBits & USE_ACCEPT_LIST) != 0);\r
3018\r
3019 DefaultInfo.UseUCast = (BOOLEAN)\r
3020 (\r
3021 (DefaultInfo.MustUseList) ||\r
3022 ((LocalPtr.DiscoveryControl->ControlBits & (DISABLE_MCAST | DISABLE_BCAST)) == (DISABLE_MCAST | DISABLE_BCAST))\r
3023 );\r
3024\r
3025 if ((DefaultInfo.UseUCast | DefaultInfo.MustUseList) && !ExtractBootServerList (\r
3026 Type,\r
3027 DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_SERVERS_IX - 1],\r
3028 &ServerListPtr\r
3029 )) {\r
3030 DEBUG ((DEBUG_WARN, "\nBcDiscover() type not in list"));\r
3031 EfiReleaseLock (&Private->Lock);\r
3032 return EFI_INVALID_PARAMETER;\r
3033 }\r
3034 }\r
3035 //\r
3036 // Info supplied - make SrvList if required\r
3037 // if we use ucast discovery or must use list, there better be one\r
3038 //\r
3039 else if (DiscoverInfoPtr->UseUCast || DiscoverInfoPtr->MustUseList) {\r
3040 //\r
3041 // there better be a list\r
3042 //\r
3043 if (DiscoverInfoPtr->IpCnt == 0) {\r
3044 DEBUG ((DEBUG_WARN, "\nBcDiscover() no bootserver list"));\r
3045 EfiReleaseLock (&Private->Lock);\r
3046 return EFI_INVALID_PARAMETER;\r
3047 }\r
3048 //\r
3049 // get its size\r
3050 //\r
3051 for (Index = Index2 = 0; Index < DiscoverInfoPtr->IpCnt; ++Index) {\r
3052 if (DiscoverInfoPtr->SrvList[Index].Type == Type) {\r
3053 if (DiscoverInfoPtr->SrvList[Index].AcceptAnyResponse) {\r
3054 if (Index2 != 0) {\r
3055 DEBUG ((DEBUG_WARN, "\nBcDiscover() accept any?"));\r
3056 EfiReleaseLock (&Private->Lock);\r
3057 return EFI_INVALID_PARAMETER;\r
3058 } else {\r
3059 Index2 = 1;\r
3060 DefaultSrvList.Ipv4List.IpCount = 0;\r
3061 ServerListPtr = &DefaultSrvList;\r
3062 break;\r
3063 }\r
3064 } else {\r
3065 ++Index2;\r
3066 }\r
3067 }\r
3068 }\r
3069\r
3070 if (Index2 == 0) {\r
3071 DEBUG ((DEBUG_WARN, "\nBcDiscover() !Index2?"));\r
3072 EfiReleaseLock (&Private->Lock);\r
3073 return EFI_INVALID_PARAMETER;\r
3074 }\r
3075\r
3076 if (ServerListPtr == NULL) {\r
3077 ServerListPtr = AllocatePool (\r
3078 sizeof (PXEV4_SERVER_LIST) + (Index2 - 1) * sizeof (EFI_IPv4_ADDRESS)\r
3079 );\r
3080\r
3081 if (ServerListPtr == NULL) {\r
3082 EfiReleaseLock (&Private->Lock);\r
3083 return EFI_OUT_OF_RESOURCES;\r
3084 }\r
3085 //\r
3086 // build an array of IP addresses from the server list\r
3087 //\r
3088 AcquiredSrvList = TRUE;\r
3089 ServerListPtr->Ipv4List.IpCount = (UINT8) Index2;\r
3090\r
3091 for (Index = Index2 = 0; Index < DiscoverInfoPtr->IpCnt; ++Index) {\r
3092 if (DiscoverInfoPtr->SrvList[Index].Type == Type) {\r
3093 CopyMem (\r
3094 &ServerListPtr->Ipv4List.IpList[Index2++],\r
3095 &DiscoverInfoPtr->SrvList[Index].IpAddr.v4,\r
3096 sizeof ServerListPtr->Ipv4List.IpList[0]\r
3097 );\r
3098 }\r
3099 }\r
3100 }\r
3101 }\r
3102\r
3103 if (DiscoverInfoPtr->MustUseList) {\r
3104 McastServerListPtr = ServerListPtr;\r
3105 }\r
3106\r
3107 if (!(DiscoverInfoPtr->UseMCast || DiscoverInfoPtr->UseBCast || DiscoverInfoPtr->UseUCast)) {\r
3108 DEBUG ((DEBUG_WARN, "\nBcDiscover() Nothing to use!\n"));\r
3109\r
3110 EfiReleaseLock (&Private->Lock);\r
3111 return EFI_INVALID_PARAMETER;\r
3112 }\r
3113\r
3114 PxebcMode->PxeDiscoverValid = PxebcMode->PxeReplyReceived = PxebcMode->PxeBisReplyReceived = FALSE;\r
3115\r
3116 StatCode = Discover (\r
3117 Private,\r
3118 Type,\r
3119 LayerPtr,\r
3120 UseBis,\r
3121 DiscoverInfoPtr,\r
3122 McastServerListPtr,\r
3123 ServerListPtr\r
3124 );\r
3125\r
3126 if (AcquiredSrvList) {\r
3127 gBS->FreePool (ServerListPtr);\r
3128 }\r
3129\r
3130 FreeMem (Private);\r
3131\r
3132 //\r
3133 // Unlock the instance data\r
3134 //\r
3135 DEBUG (\r
3136 (DEBUG_INFO,\r
3137 "\nBcDiscover() status == %r (%Xh)\n",\r
3138 StatCode,\r
3139 StatCode)\r
3140 );\r
3141\r
3142 EfiReleaseLock (&Private->Lock);\r
3143 return StatCode;\r
3144}\r
3145\r
3146/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
3147\r
3148/**\r
3149\r
3150\r
3151**/\r
3152EFI_STATUS\r
3153EFIAPI\r
3154BcSetPackets (\r
3155 IN EFI_PXE_BASE_CODE_PROTOCOL * This,\r
3156 BOOLEAN *NewDhcpDiscoverValid, OPTIONAL\r
3157 BOOLEAN *NewDhcpAckReceived, OPTIONAL\r
3158 BOOLEAN *NewProxyOfferReceived, OPTIONAL\r
3159 BOOLEAN *NewPxeDiscoverValid, OPTIONAL\r
3160 BOOLEAN *NewPxeReplyReceived, OPTIONAL\r
3161 BOOLEAN *NewPxeBisReplyReceived, OPTIONAL\r
3162 IN EFI_PXE_BASE_CODE_PACKET * NewDhcpDiscover, OPTIONAL\r
3163 IN EFI_PXE_BASE_CODE_PACKET * NewDhcpAck, OPTIONAL\r
3164 IN EFI_PXE_BASE_CODE_PACKET * NewProxyOffer, OPTIONAL\r
3165 IN EFI_PXE_BASE_CODE_PACKET * NewPxeDiscover, OPTIONAL\r
3166 IN EFI_PXE_BASE_CODE_PACKET * NewPxeReply, OPTIONAL\r
3167 IN EFI_PXE_BASE_CODE_PACKET * NewPxeBisReply OPTIONAL\r
3168 )\r
3169{\r
3170 EFI_PXE_BASE_CODE_MODE *PxebcMode;\r
3171 EFI_STATUS Status;\r
772db4bb 3172 PXE_BASECODE_DEVICE *Private;\r
3173\r
3174 //\r
3175 // Lock the instance data and make sure started\r
3176 //\r
772db4bb 3177\r
3178 if (This == NULL) {\r
3179 DEBUG ((DEBUG_ERROR, "BC *This pointer == NULL"));\r
3180 return EFI_INVALID_PARAMETER;\r
3181 }\r
3182\r
3183 Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE);\r
3184\r
3185 if (Private == NULL) {\r
3186 DEBUG ((DEBUG_ERROR, "PXE_BASECODE_DEVICE poiner == NULL"));\r
3187 return EFI_INVALID_PARAMETER;\r
3188 }\r
3189\r
3190 EfiAcquireLock (&Private->Lock);\r
3191\r
3192 if (This->Mode == NULL || !This->Mode->Started) {\r
3193 DEBUG ((DEBUG_ERROR, "BC was not started."));\r
3194 EfiReleaseLock (&Private->Lock);\r
3195 return EFI_NOT_STARTED;\r
3196 }\r
3197\r
3198 PxebcMode = Private->EfiBc.Mode;\r
3199\r
3200 if (Private->DhcpPacketBuffer == NULL) {\r
3201 Status = gBS->AllocatePool (\r
3202 EfiBootServicesData,\r
3203 sizeof (DHCP_RECEIVE_BUFFER) * (PXE_BIS_INDEX + 1),\r
3204 &Private->DhcpPacketBuffer\r
3205 );\r
3206\r
3207 if (EFI_ERROR (Status) || Private->DhcpPacketBuffer == NULL) {\r
3208 Private->DhcpPacketBuffer = NULL;\r
3209 EfiReleaseLock (&Private->Lock);\r
3210 return EFI_OUT_OF_RESOURCES;\r
3211 }\r
3212 }\r
3213 //\r
3214 // Issue BC command\r
3215 //\r
3216 //\r
3217 // reset\r
3218 //\r
3219 Private->FileSize = 0;\r
3220 if (NewDhcpDiscoverValid != NULL) {\r
3221 PxebcMode->DhcpDiscoverValid = *NewDhcpDiscoverValid;\r
3222 }\r
3223\r
3224 if (NewDhcpAckReceived != NULL) {\r
3225 PxebcMode->DhcpAckReceived = *NewDhcpAckReceived;\r
3226 }\r
3227\r
3228 if (NewProxyOfferReceived != NULL) {\r
3229 PxebcMode->ProxyOfferReceived = *NewProxyOfferReceived;\r
3230 }\r
3231\r
3232 if (NewPxeDiscoverValid != NULL) {\r
3233 PxebcMode->PxeDiscoverValid = *NewPxeDiscoverValid;\r
3234 }\r
3235\r
3236 if (NewPxeReplyReceived != NULL) {\r
3237 PxebcMode->PxeReplyReceived = *NewPxeReplyReceived;\r
3238 }\r
3239\r
3240 if (NewPxeBisReplyReceived != NULL) {\r
3241 PxebcMode->PxeBisReplyReceived = *NewPxeBisReplyReceived;\r
3242 }\r
3243\r
3244 if (NewDhcpDiscover != NULL) {\r
3245 CopyMem (\r
3246 &PxebcMode->DhcpDiscover,\r
3247 NewDhcpDiscover,\r
3248 sizeof *NewDhcpDiscover\r
3249 );\r
3250 }\r
3251\r
3252 if (NewDhcpAck != NULL) {\r
3253 CopyParse (Private, &PxebcMode->DhcpAck, NewDhcpAck, DHCPV4_ACK_INDEX);\r
3254 }\r
3255\r
3256 if (NewProxyOffer != NULL) {\r
3257 CopyParse (Private, &PxebcMode->ProxyOffer, NewProxyOffer, PXE_OFFER_INDEX);\r
3258 }\r
3259\r
3260 if (NewPxeDiscover != NULL) {\r
3261 CopyMem (\r
3262 &PxebcMode->PxeDiscover,\r
3263 NewPxeDiscover,\r
3264 sizeof *NewPxeDiscover\r
3265 );\r
3266 }\r
3267\r
3268 if (NewPxeReply != NULL) {\r
3269 CopyParse (Private, &PxebcMode->PxeReply, NewPxeReply, PXE_ACK_INDEX);\r
3270 }\r
3271\r
3272 if (NewPxeBisReply != NULL) {\r
3273 CopyParse (Private, &PxebcMode->PxeBisReply, NewPxeBisReply, PXE_BIS_INDEX);\r
3274 }\r
3275 //\r
3276 // Unlock the instance data\r
3277 //\r
3278 EfiReleaseLock (&Private->Lock);\r
3279 return EFI_SUCCESS;\r
3280}\r
3281\r
3282/* eof - pxe_bc_dhcp.c */\r