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