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