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