3 Copyright (c) 2004 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 DHCP and PXE discovery protocol implementations.
25 EFI_PXE_BASE_CODE_UDP_PORT DhcpServerPort
= DHCP_SERVER_PORT
;
26 EFI_PXE_BASE_CODE_UDP_PORT DHCPClientPort
= DHCP_CLIENT_PORT
;
27 EFI_PXE_BASE_CODE_UDP_PORT PseudoDhcpServerPort
= PXE_DISCOVERY_PORT
;
28 #define PSEUDO_DHCP_CLIENT_PORT PseudoDhcpServerPort
29 EFI_IP_ADDRESS BroadcastIP
= {{0xffffffff}};
30 EFI_IP_ADDRESS DefaultSubnetMask
= {{0xffffff00}};
33 DHCPV4_OP_STRUCT
*OpPtr
;
34 PXE_OP_SERVER_LIST
*BootServersStr
;
35 PXE_SERVER_LIST
*BootServerList
;
36 PXE_BOOT_MENU_ENTRY
*BootMenuItem
;
37 PXE_OP_DISCOVERY_CONTROL
*DiscoveryControl
;
38 PXE_OP_BOOT_MENU
*BootMenu
;
39 PXE_OP_BOOT_ITEM
*BootItem
;
40 DHCPV4_OP_VENDOR_OPTIONS
*VendorOptions
;
41 DHCPV4_OP_OVERLOAD
*Overload
;
42 DHCPV4_OP_CLASS
*PxeClassStr
;
43 DHCPV4_OP_SUBNET_MASK
*SubnetMaskStr
;
44 DHCPV4_OP_MESSAGE_TYPE
*MessageType
;
50 // option structure for DHCPREQUEST at end of DISCOVER options
51 // and for DHCPDECLINE
53 const struct requestopendstr
{
54 DHCPV4_OP_REQUESTED_IP OpReqIP
;
55 DHCPV4_OP_SERVER_IP DhcServerIpPtr
;
62 DHCPV4_OPTION_LENGTH(DHCPV4_OP_REQUESTED_IP
)
68 DHCPV4_OPTION_LENGTH(DHCPV4_OP_SERVER_IP
)
76 #define DHCP_REQ_OPTIONS (*(struct requestopendstr *) DHCPV4_OPTIONS_BUFFER.End)
78 PXE_OP_BOOT_ITEM DefaultBootItem
= {
81 DHCPV4_OPTION_LENGTH(PXE_OP_BOOT_ITEM
)
88 // PXE discovery control default structure
90 PXE_OP_DISCOVERY_CONTROL DefaultDisCtl
= {
91 { VEND_PXE_DISCOVERY_CONTROL
, DHCPV4_OPTION_LENGTH(PXE_OP_DISCOVERY_CONTROL
) },
96 // PXE credentials option structure
103 DHCPV4_OP_HEADER Header
;
104 PXE_CREDENTIAL Credentials
[1];
105 } PXE_OP_CREDENTIAL_TYPES
;
108 // option structure for PXE discover (without credentials)
110 typedef struct { // discoveropendstr {
111 DHCPV4_OP_HEADER Header
; // vendor options
112 PXE_OP_BOOT_ITEM BootItem
;
113 UINT8 End
[1]; // if credentials option, it starts here
114 } PXE_DISCOVER_OPTIONS
;
116 #define DISCOVERoptions (*(PXE_DISCOVER_OPTIONS *) DHCPV4_OPTIONS_BUFFER.End)
117 #define DISCREDoptions (*(PXE_OP_CREDENTIAL_TYPES *) DISCOVERoptions.End)
120 // common option beginning for all our DHCP messages except
121 // DHCPDECLINE and DHCPRELEASE
125 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType
;
126 DHCPV4_OP_MAX_MESSAGE_SIZE DhcpMaxMessageSize
;
127 DHCPV4_OP_REQUESTED_OPTIONS DhcpRequestedOptions
;
128 DHCPV4_OP_PLATFORM_ID DhcpPlatformId
;
129 DHCPV4_OP_NETWORK_INTERFACE DhcpNetworkInterface
;
130 DHCPV4_OP_ARCHITECTURE_TYPE DhcpClientArchitecture
;
131 DHCPV4_OP_CLASS_ID DhcpClassIdentifier
;
135 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
141 DHCPOpStart
.DhcpCookie
[0] = 99;
142 DHCPOpStart
.DhcpCookie
[1] = 130;
143 DHCPOpStart
.DhcpCookie
[2] = 83;
144 DHCPOpStart
.DhcpCookie
[3] = 99;
145 DHCPOpStart
.DhcpMessageType
.Header
.OpCode
= OP_DHCP_MESSAGE_TYPE
;
146 DHCPOpStart
.DhcpMessageType
.Header
.Length
= 1;
147 DHCPOpStart
.DhcpMessageType
.Type
= DHCPDISCOVER
;
148 DHCPOpStart
.DhcpMaxMessageSize
.Header
.OpCode
= OP_DHCP_MAX_MESSAGE_SZ
;
149 DHCPOpStart
.DhcpMaxMessageSize
.Header
.Length
= 2;
150 DHCPOpStart
.DhcpMaxMessageSize
.MaxSize
[0] = MAX_DHCP_MSG_SZ
>> 8;
151 DHCPOpStart
.DhcpMaxMessageSize
.MaxSize
[1] = MAX_DHCP_MSG_SZ
& 0xff;
152 DHCPOpStart
.DhcpRequestedOptions
.Header
.OpCode
= OP_DHCP_PARM_REQ_LIST
;
153 DHCPOpStart
.DhcpRequestedOptions
.Header
.Length
= sizeof (DHCPV4_REQUESTED_OPTIONS_DATA
);
154 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_SUBNET_MASK
= OP_SUBNET_MASK
; /* 1 */
155 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_TIME_OFFSET
= OP_TIME_OFFSET
; /* 2 */
156 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_ROUTER_LIST
= OP_ROUTER_LIST
; /* 3 */
157 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_TIME_SERVERS
= OP_TIME_SERVERS
; /* 4 */
158 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NAME_SERVERS
= OP_NAME_SERVERS
; /* 5 */
159 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DNS_SERVERS
= OP_DNS_SERVERS
; /* 6 */
160 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_HOST_NAME
= OP_HOST_NAME
; /* 12 */
161 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_BOOT_FILE_SZ
= OP_BOOT_FILE_SZ
; /* 13 */
162 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DOMAIN_NAME
= OP_DOMAIN_NAME
; /* 15 */
163 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_ROOT_PATH
= OP_ROOT_PATH
; /* 17 */
164 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_EXTENSION_PATH
= OP_EXTENSION_PATH
; /* 18 */
165 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_MAX_DATAGRAM_SZ
= OP_MAX_DATAGRAM_SZ
; /* 22 */
166 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DEFAULT_TTL
= OP_DEFAULT_TTL
; /* 23 */
167 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_BROADCAST_ADD
= OP_BROADCAST_ADD
; /* 28 */
168 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NIS_DOMAIN_NAME
= OP_NIS_DOMAIN_NAME
; /* 40 */
169 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NIS_SERVERS
= OP_NIS_SERVERS
; /* 41 */
170 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NTP_SERVERS
= OP_NTP_SERVERS
; /* 42 */
171 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_VENDOR_SPECIFIC
= OP_VENDOR_SPECIFIC
; /* 43 */
172 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_REQ_IP_ADD
= OP_DHCP_REQ_IP_ADD
; /* 50 */
173 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_LEASE_TIME
= OP_DHCP_LEASE_TIME
; /* 51 */
174 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_SERVER_IP
= OP_DHCP_SERVER_IP
; /* 54 */
175 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_RENEWAL_TIME
= OP_DHCP_RENEWAL_TIME
; /* 58 */
176 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_REBINDING_TIME
= OP_DHCP_REBINDING_TIME
; /* 59 */
177 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_CLASS_IDENTIFIER
= OP_DHCP_CLASS_IDENTIFIER
; /* 60 */
178 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_TFTP_SERVER_NAME
= OP_DHCP_TFTP_SERVER_NAME
; /* 66 */
179 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_BOOTFILE
= OP_DHCP_BOOTFILE
; /* 67 */
180 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_PLATFORM_ID
= OP_DHCP_PLATFORM_ID
; /* 97 */
181 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption128
= 128;
182 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption129
= 129;
183 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption130
= 130;
184 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption131
= 131;
185 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption132
= 132;
186 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption133
= 133, DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption134
= 134;
187 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption135
= 135;
188 DHCPOpStart
.DhcpPlatformId
.Header
.OpCode
= OP_DHCP_PLATFORM_ID
;
189 DHCPOpStart
.DhcpPlatformId
.Header
.Length
= DHCPV4_OPTION_LENGTH (DHCPV4_OP_PLATFORM_ID
);
190 DHCPOpStart
.DhcpNetworkInterface
.Header
.OpCode
= OP_DHCP_NETWORK_ARCH
;
191 DHCPOpStart
.DhcpNetworkInterface
.Header
.Length
= DHCPV4_OPTION_LENGTH (DHCPV4_OP_NETWORK_INTERFACE
);
192 DHCPOpStart
.DhcpNetworkInterface
.Type
= 0;
193 DHCPOpStart
.DhcpNetworkInterface
.MajorVersion
= 0;
194 DHCPOpStart
.DhcpNetworkInterface
.MinorVersion
= 0;
195 DHCPOpStart
.DhcpClientArchitecture
.Header
.OpCode
= OP_DHCP_SYSTEM_ARCH
;
196 DHCPOpStart
.DhcpClientArchitecture
.Header
.Length
= DHCPV4_OPTION_LENGTH (DHCPV4_OP_ARCHITECTURE_TYPE
);
197 DHCPOpStart
.DhcpClientArchitecture
.Type
= HTONS (SYS_ARCH
);
198 DHCPOpStart
.DhcpClassIdentifier
.Header
.OpCode
= OP_DHCP_CLASS_IDENTIFIER
;
199 DHCPOpStart
.DhcpClassIdentifier
.Header
.Length
= sizeof (DHCPV4_CLASS_ID_DATA
);
201 DHCPOpStart
.DhcpClassIdentifier
.Data
.ClassIdentifier
,
203 sizeof ("PXEClient:")
205 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.Lit2
, "Arch:", sizeof ("Arch:"));
207 DHCPOpStart
.DhcpClassIdentifier
.Data
.ArchitectureType
,
211 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.Lit3
, ":", sizeof (":"));
212 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.InterfaceName
, "XXXX", sizeof ("XXXX"));
213 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.Lit4
, ":", sizeof (":"));
214 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.UndiMajor
, "yyy", sizeof ("yyy"));
215 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.UndiMinor
, "xxx", sizeof ("xxx"));
216 DHCPOpStart
.End
[0] = OP_END
;
219 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
222 // DHCPDECLINE option structure
224 struct opdeclinestr
{
226 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType
;
227 struct requestopendstr OpDeclineEnd
;
230 #define DHCPDECLINEoptions (*(struct opdeclinestr *) DHCPV4_TRANSMIT_BUFFER.options)
233 // DHCPRELEASE option structure
235 struct opreleasestr
{
237 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType
;
238 DHCPV4_OP_SERVER_IP DhcServerIpPtr
;
242 #define DHCPRELEASEoptions (*(struct opreleasestr *) DHCPV4_TRANSMIT_BUFFER.options)
245 // array of PXE vendor options in which we are interested
246 // value 0 -> not of interest, else value is index into PXE OPTION array
247 // option values from 1 to MAX_OUR_PXE_OPT
249 UINT8 ourPXEopts
[MAX_OUR_PXE_OPT
] = {
250 VEND_PXE_MTFTP_IP_IX
, // multicast IP address of bootfile for MTFTP listen
251 VEND_PXE_MTFTP_CPORT_IX
, // UDP Port to monitor for MTFTP responses - Intel order
252 VEND_PXE_MTFTP_SPORT_IX
, // Server UDP Port for MTFTP open - Intel order
253 VEND_PXE_MTFTP_TMOUT_IX
, // Listen timeout - secs
254 VEND_PXE_MTFTP_DELAY_IX
, // Transmission timeout - secs
255 VEND_PXE_DISCOVERY_CONTROL_IX
, // bit field
256 VEND_PXE_DISCOVERY_MCAST_ADDR_IX
, // boot server discovery multicast address
257 VEND_PXE_BOOT_SERVERS_IX
, // list of boot servers of form tp(2) cnt(1) ips[cnt]
258 VEND_PXE_BOOT_MENU_IX
,
259 VEND_PXE_BOOT_PROMPT_IX
,
260 VEND_PXE_MCAST_ADDRS_ALLOC_IX
, // not used by client
261 VEND_PXE_CREDENTIAL_TYPES_IX
,
262 VEND_13_IX
, // not used by client
263 VEND_14_IX
, // not used by client
264 VEND_15_IX
, // not used by client
265 VEND_16_IX
, // not used by client
266 VEND_17_IX
, // not used by client
267 VEND_18_IX
, // not used by client
268 VEND_19_IX
, // not used by client
269 VEND_20_IX
, // not used by client
270 VEND_21_IX
, // not used by client
271 VEND_22_IX
, // not used by client
272 VEND_23_IX
, // not used by client
273 VEND_24_IX
, // not used by client
274 VEND_25_IX
, // not used by client
275 VEND_26_IX
, // not used by client
276 VEND_27_IX
, // not used by client
277 VEND_28_IX
, // not used by client
278 VEND_29_IX
, // not used by client
279 VEND_30_IX
, // not used by client
280 VEND_31_IX
, // not used by client
281 VEND_32_IX
, // not used by client
282 VEND_33_IX
, // not used by client
283 VEND_34_IX
, // not used by client
284 VEND_35_IX
, // not used by client
285 VEND_36_IX
, // not used by client
286 VEND_37_IX
, // not used by client
287 VEND_38_IX
, // not used by client
288 VEND_39_IX
, // not used by client
289 VEND_40_IX
, // not used by client
290 VEND_41_IX
, // not used by client
291 VEND_42_IX
, // not used by client
292 VEND_43_IX
, // not used by client
293 VEND_44_IX
, // not used by client
294 VEND_45_IX
, // not used by client
295 VEND_46_IX
, // not used by client
296 VEND_47_IX
, // not used by client
297 VEND_48_IX
, // not used by client
298 VEND_49_IX
, // not used by client
299 VEND_50_IX
, // not used by client
300 VEND_51_IX
, // not used by client
301 VEND_52_IX
, // not used by client
302 VEND_53_IX
, // not used by client
303 VEND_54_IX
, // not used by client
304 VEND_55_IX
, // not used by client
305 VEND_56_IX
, // not used by client
306 VEND_57_IX
, // not used by client
307 VEND_58_IX
, // not used by client
308 VEND_59_IX
, // not used by client
309 VEND_60_IX
, // not used by client
310 VEND_61_IX
, // not used by client
311 VEND_62_IX
, // not used by client
312 VEND_63_IX
, // not used by client
313 VEND_64_IX
, // not used by client
314 VEND_65_IX
, // not used by client
315 VEND_66_IX
, // not used by client
316 VEND_67_IX
, // not used by client
317 VEND_68_IX
, // not used by client
318 VEND_69_IX
, // not used by client
319 VEND_70_IX
, // not used by client
320 VEND_PXE_BOOT_ITEM_IX
323 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
326 // array of options in which we are interested
327 // value 0 -> not of interest, else value is index into OPTION array
328 // option values from 1 to MAX_OUR_OPT
330 UINT8 OurDhcpOptions
[MAX_OUR_OPT
] = {
331 OP_SUBNET_MASK_IX
, // OP_SUBNET_MASK 1 // data is the subnet mask
332 OP_TIME_OFFSET_IX
, // OP_TIME_OFFSET 2 // data is the time offset of subnet to UTC in seconds
333 OP_ROUTER_LIST_IX
, // OP_ROUTER_LIST 3 // list of routers on subnet
334 OP_TIME_SERVERS_IX
, // OP_TIME_SERVERS 4 // list of time servers available
335 OP_NAME_SERVERS_IX
, // OP_NAME_SERVERS 5 // list of name servers available
336 OP_DNS_SERVERS_IX
, // OP_DNS_SERVERS 6 // list of DNS servers available
337 OP_LOG_SERVERS_IX
, // OP_LOG_SERVERS 7
338 OP_COOKIE_SERVERS_IX
, // OP_COOKIE_SERVERS 8
339 OP_LPR_SREVERS_IX
, // OP_LPR_SREVERS 9
340 OP_IMPRESS_SERVERS_IX
, // OP_IMPRESS_SERVERS 10
341 OP_RES_LOC_SERVERS_IX
, // OP_RES_LOC_SERVERS 11
342 OP_HOST_NAME_IX
, // OP_HOST_NAME 12 // client name
343 OP_BOOT_FILE_SZ_IX
, // OP_BOOT_FILE_SZ 13 // number of 512 blocks of boot file
344 OP_DUMP_FILE_IX
, // OP_DUMP_FILE 14 // path name of dump file if client crashes
345 OP_DOMAIN_NAME_IX
, // OP_DOMAIN_NAME 15 // domain name to use
346 OP_SWAP_SERVER_IX
, // OP_SWAP_SERVER 16
347 OP_ROOT_PATH_IX
, // OP_ROOT_PATH 17 // path name containing root disk
348 OP_EXTENSION_PATH_IX
, // OP_EXTENSION_PATH 18 // name of TFTP downloadable file of form of OP
349 OP_IP_FORWARDING_IX
, // OP_IP_FORWARDING 19 // enable/disable IP packet forwarding
350 OP_NON_LOCAL_SRC_RTE_IX
, // OP_NON_LOCAL_SRC_RTE 20 // enable/disable non local source routing
351 OP_POLICY_FILTER_IX
, // OP_POLICY_FILTER 21 // policy filters for non local source routing
352 OP_MAX_DATAGRAM_SZ_IX
, // OP_MAX_DATAGRAM_SZ 22 // maximum datagram reassembly size
353 OP_DEFAULT_TTL_IX
, // OP_DEFAULT_TTL 23 // default IP time to live
354 OP_MTU_AGING_TIMEOUT_IX
, // OP_MTU_AGING_TIMEOUT 24
355 OP_MTU_SIZES_IX
, // OP_MTU_SIZES 25
356 OP_MTU_TO_USE_IX
, // OP_MTU_TO_USE 26
357 OP_ALL_SUBNETS_LOCAL_IX
, // OP_ALL_SUBNETS_LOCAL 27
358 OP_BROADCAST_ADD_IX
, // OP_BROADCAST_ADD 28 // broadcast address used on subnet
359 OP_PERFORM_MASK_DISCOVERY_IX
, // OP_PERFORM_MASK_DISCOVERY 29 // perform mask discovery using ICMP
360 OP_RESPOND_TO_MASK_REQ_IX
, // OP_RESPOND_TO_MASK_REQ 30 // respond to subnet mask requests using ICMP
361 OP_PERFORM_ROUTER_DISCOVERY_IX
, // OP_PERFORM_ROUTER_DISCOVERY 31
362 OP_ROUTER_SOLICIT_ADDRESS_IX
, // OP_ROUTER_SOLICIT_ADDRESS 32
363 OP_STATIC_ROUTER_LIST_IX
, // OP_STATIC_ROUTER_LIST 33 // list of dest/route pairs
364 OP_USE_ARP_TRAILERS_IX
, // OP_USE_ARP_TRAILERS 34
365 OP_ARP_CACHE_TIMEOUT_IX
, // OP_ARP_CACHE_TIMEOUT 35
366 OP_ETHERNET_ENCAPSULATION_IX
, // OP_ETHERNET_ENCAPSULATION 36 // 0 -> RFC 894, 1 -> IEEE 802.3 (RFC 1042)
367 OP_TCP_DEFAULT_TTL_IX
, // OP_TCP_DEFAULT_TTL 37 // default time to live when sending TCP segments
368 OP_TCP_KEEP_ALIVE_INT_IX
, // OP_TCP_KEEP_ALIVE_INT 38 // keep alive interval in seconds
369 OP_KEEP_ALIVE_GARBAGE_IX
, // OP_KEEP_ALIVE_GARBAGE 39
370 OP_NIS_DOMAIN_NAME_IX
, // OP_NIS_DOMAIN_NAME 40
371 OP_NIS_SERVERS_IX
, // OP_NIS_SERVERS 41
372 OP_NTP_SERVERS_IX
, // OP_NTP_SERVERS 42
373 OP_VENDOR_SPECIFIC_IX
, // OP_VENDOR_SPECIFIC 43
374 OP_NBNS_SERVERS_IX
, // OP_NBNS_SERVERS 44
375 OP_NBDD_SERVERS_IX
, // OP_NBDD_SERVERS 45
376 OP_NETBIOS_NODE_TYPE_IX
, // OP_NETBIOS_NODE_TYPE 46
377 OP_NETBIOS_SCOPE_IX
, // OP_NETBIOS_SCOPE 47
378 OP_XWINDOW_SYSTEM_FONT_SERVERS_IX
, // OP_XWINDOW_SYSTEM_FONT_SERVERS 48
379 OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS_IX
, // OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49
380 OP_DHCP_REQ_IP_ADD_IX
, // OP_DHCP_REQ_IP_ADD 50 // requested IP address - in DHCPDISCOVER
381 OP_DHCP_LEASE_TIME_IX
, // OP_DHCP_LEASE_TIME 51 // lease time requested/granted
382 OP_DHCP_OPTION_OVERLOAD_IX
, // OP_DHCP_OPTION_OVERLOAD 52 // file/server name/both used to hold options
383 OP_DHCP_MESSAGE_TYPE_IX
, // OP_DHCP_MESSAGE_TYPE 53 // message type
384 OP_DHCP_SERVER_IP_IX
, // OP_DHCP_SERVER_IP 54 // IP of server
385 OP_DHCP_PARM_REQ_LIST_IX
, // OP_DHCP_PARM_REQ_LIST 55 // list of requested parameters
386 OP_DHCP_ERROR_MESSAGE_IX
, // OP_DHCP_ERROR_MESSAGE 56 // in DHCPNAK or DECLINE messages
387 OP_DHCP_MAX_MESSAGE_SZ_IX
, // OP_DHCP_MAX_MESSAGE_SZ 57 // maximum DHCP message size client will accept
388 OP_DHCP_RENEWAL_TIME_IX
, // OP_DHCP_RENEWAL_TIME 58 // time in seconds before transitioning to RENEWING state
389 OP_DHCP_REBINDING_TIME_IX
, // OP_DHCP_REBINDING_TIME 59 // time in seconds before transitioning to REBINDING state
390 OP_DHCP_CLASS_IDENTIFIER_IX
, // OP_DHCP_CLASS_IDENTIFIER 60
391 OP_DHCP_CLIENT_IDENTIFIER_IX
, // OP_DHCP_CLIENT_IDENTIFIER 61
392 OP_RESERVED62_IX
, // OP_RESERVED62
393 OP_RESERVED63_IX
, // OP_RESERVED63
394 OP_NISPLUS_DOMAIN_NAME_IX
, // OP_NISPLUS_DOMAIN_NAME 64
395 OP_NISPLUS_SERVERS_IX
, // OP_NISPLUS_SERVERS 65
396 OP_DHCP_TFTP_SERVER_NAME_IX
, // OP_DHCP_TFTP_SERVER_NAME 66
397 OP_DHCP_BOOTFILE_IX
// OP_DHCP_BOOTFILE 67
400 #define RxBuf ((DHCP_RECEIVE_BUFFER *) (Private->ReceiveBuffers))
404 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
408 @param Smbios Pointer to SMBIOS structure
409 @param StringNumber String number to return. 0 is used to skip all
410 strings and point to the next SMBIOS structure.
412 @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == 0
416 PxeBcLibGetSmbiosString (
417 IN SMBIOS_STRUCTURE_POINTER
*Smbios
,
418 IN UINT16 StringNumber
425 // Skip over formatted section
427 String
= (CHAR8
*) (Smbios
->Raw
+ Smbios
->Hdr
->Length
);
430 // Look through unformated section
432 for (Index
= 1; Index
<= StringNumber
|| StringNumber
== 0; Index
++) {
433 if (StringNumber
== Index
) {
439 for (; *String
!= 0; String
++)
445 // If double NULL then we are done.
446 // Return pointer to next structure in Smbios.
447 // if you pass in a 0 you will always get here
449 Smbios
->Raw
= (UINT8
*)++String
;
459 This function gets system guid and serial number from the smbios table
461 @param SystemGuid The pointer of returned system guid
462 @param SystemSerialNumber The pointer of returned system serial number
464 @retval EFI_SUCCESS Successfully get the system guid and system serial
466 @retval EFI_NOT_FOUND Not find the SMBIOS table
470 PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
471 IN EFI_GUID
*SystemGuid
,
472 OUT CHAR8
**SystemSerialNumber
476 SMBIOS_TABLE_ENTRY_POINT
*SmbiosTable
;
477 SMBIOS_STRUCTURE_POINTER Smbios
;
478 SMBIOS_STRUCTURE_POINTER SmbiosEnd
;
481 Status
= EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid
, (VOID
**) &SmbiosTable
);
483 if (EFI_ERROR (Status
)) {
484 return EFI_NOT_FOUND
;
487 Smbios
.Hdr
= (SMBIOS_STRUCTURE
*) (UINTN
) SmbiosTable
->TableAddress
;
488 SmbiosEnd
.Raw
= (UINT8
*) (UINTN
) (SmbiosTable
->TableAddress
+ SmbiosTable
->TableLength
);
490 for (Index
= 0; Index
< SmbiosTable
->TableLength
; Index
++) {
491 if (Smbios
.Hdr
->Type
== 1) {
492 if (Smbios
.Hdr
->Length
< 0x19) {
494 // Older version did not support Guid and Serial number
499 // SMBIOS tables are byte packed so we need to do a byte copy to
500 // prevend alignment faults on Itanium-based platform.
502 CopyMem (SystemGuid
, &Smbios
.Type1
->Uuid
, sizeof (EFI_GUID
));
503 *SystemSerialNumber
= PxeBcLibGetSmbiosString (&Smbios
, Smbios
.Type1
->SerialNumber
);
508 // Make Smbios point to the next record
510 PxeBcLibGetSmbiosString (&Smbios
, 0);
512 if (Smbios
.Raw
>= SmbiosEnd
.Raw
) {
514 // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e.
515 // given this we must double check against the lenght of
525 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
528 // add router list to list
532 PXE_BASECODE_DEVICE
*Private
,
533 DHCPV4_OP_IP_LIST
*IpListPtr
536 EFI_IP_ADDRESS TmpIp
;
540 if (IpListPtr
== NULL
) {
544 for (Index
= 0, num
= IpListPtr
->Header
.Length
>> 2; Index
< num
; ++Index
) {
545 CopyMem (&TmpIp
, &IpListPtr
->IpList
[Index
], 4);
546 Ip4AddRouter (Private
, &TmpIp
);
550 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
553 // send ARP for our IP - fail if someone has it
557 PXE_BASECODE_DEVICE
*Private
560 EFI_MAC_ADDRESS DestMac
;
561 EFI_STATUS EfiStatus
;
563 ZeroMem (&DestMac
, sizeof DestMac
);
565 if (GetHwAddr(Private
, (EFI_IP_ADDRESS
*)&DHCP_REQ_OPTIONS
.OpReqIP
.Ip
, (EFI_MAC_ADDRESS
*)&DestMac
)
566 || DoArp(Private
, (EFI_IP_ADDRESS
*)&DHCP_REQ_OPTIONS
.OpReqIP
.Ip
, (EFI_MAC_ADDRESS
*)&DestMac
) == EFI_SUCCESS
) {
567 return FALSE
; // somebody else has this IP
571 (EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->StationIp
,
572 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
573 sizeof (EFI_IPv4_ADDRESS
)
576 Private
->GoodStationIp
= TRUE
;
578 if (!Private
->UseIgmpv1Reporting
) {
582 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
586 EfiStatus
= gBS
->CreateEvent (
591 &Private
->Igmpv1TimeoutEvent
594 if (EFI_ERROR (EfiStatus
)) {
595 Private
->Igmpv1TimeoutEvent
= NULL
;
599 EfiStatus
= gBS
->SetTimer (
600 Private
->Igmpv1TimeoutEvent
,
602 (UINT64
) V1ROUTER_PRESENT_TIMEOUT
* 10000000
605 if (EFI_ERROR (EfiStatus
)) {
606 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
607 Private
->Igmpv1TimeoutEvent
= NULL
;
613 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
616 PXE_BASECODE_DEVICE
*Private
,
617 DHCP_RECEIVE_BUFFER
*RxBufPtr
622 (DHCPV4_OP_IP_LIST
*) RxBufPtr
->OpAdds
.PktOptAdds
[OP_ROUTER_LIST_IX
- 1]
626 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
629 PXE_BASECODE_DEVICE
*Private
,
630 EFI_IP_ADDRESS
*ServerIpPtr
,
631 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
632 EFI_IP_ADDRESS
*ClientIpPtr
,
633 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
638 Len
= sizeof DHCPV4_TRANSMIT_BUFFER
;
642 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
651 Private
->TransmitBuffer
655 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
658 // initialize the DHCP structure
666 PXE_BASECODE_DEVICE
*Private
671 CHAR8
*SystemSerialNumber
;
672 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
674 PxebcMode
= Private
->EfiBc
.Mode
;
676 ZeroMem (&DHCPV4_TRANSMIT_BUFFER
, sizeof (DHCPV4_STRUCT
));
677 DHCPV4_TRANSMIT_BUFFER
.op
= BOOTP_REQUEST
;
678 DHCPV4_TRANSMIT_BUFFER
.htype
= Private
->SimpleNetwork
->Mode
->IfType
;
679 DHCPV4_TRANSMIT_BUFFER
.flags
= HTONS (DHCP_BROADCAST_FLAG
);
680 CopyMem (&DHCPV4_OPTIONS_BUFFER
, (VOID
*) &DHCPOpStart
, sizeof (DHCPOpStart
));
683 // default to hardware address
685 HwAddrLen
= Private
->SimpleNetwork
->Mode
->HwAddressSize
;
687 if (HwAddrLen
> sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
) {
688 HwAddrLen
= sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
;
691 String
= (UINT8
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
;
693 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
694 (EFI_GUID
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
,
697 if (PxebcMode
->SendGUID
) {
698 HwAddrLen
= sizeof (EFI_GUID
);
699 String
= (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
;
703 // GUID not yet set - send all 0xff's to show programable (via SetVariable)
704 // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);
705 // GUID not yet set - send all 0's to show not programable
707 ZeroMem (DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
, sizeof (EFI_GUID
));
710 DHCPV4_TRANSMIT_BUFFER
.hlen
= (UINT8
) HwAddrLen
;
711 CopyMem (DHCPV4_TRANSMIT_BUFFER
.chaddr
, String
, HwAddrLen
);
715 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
,
716 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
719 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.Type
= Private
->NiiPtr
->Type
;
720 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
= Private
->NiiPtr
->MajorVer
;
721 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
= Private
->NiiPtr
->MinorVer
;
723 *(C4Str
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.InterfaceName
= *(C4Str
*) Private
->NiiPtr
->StringId
;
726 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
,
727 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
,
728 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
732 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
,
733 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
,
734 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
738 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
741 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
754 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
767 LocalPtr
.BytePtr
= ptr
;
768 if (Op
<= MAX_OUR_PXE_OPT
) {
769 Index
= ourPXEopts
[Op
- 1];
771 RxBufPtr
->OpAdds
.PxeOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
772 status
|= 1 << Index
;
773 if (Index
== VEND_PXE_BOOT_ITEM
&& LocalPtr
.BootItem
->Header
.Length
== 3) {
774 RxBufPtr
->OpAdds
.Status
|= USE_THREE_BYTE
;
785 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
788 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
798 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
811 LocalPtr
.BytePtr
= ptr
;
812 if (Op
<= MAX_OUR_OPT
) {
813 Index
= OurDhcpOptions
[Op
- 1];
815 RxBufPtr
->OpAdds
.PktOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
816 if (Index
== OP_VENDOR_SPECIFIC_IX
) {
818 status
= DecodePxeOptions (
820 (UINT8
*) LocalPtr
.VendorOptions
->VendorOptions
,
821 LocalPtr
.VendorOptions
->Header
.Length
824 RxBufPtr
->OpAdds
.Status
|= PXE_TYPE
;
826 // check for all the MTFTP info options present - any missing is a nogo
828 if ((status
& WfM11a_OPTS
) == WfM11a_OPTS
) {
829 RxBufPtr
->OpAdds
.Status
|= WfM11a_TYPE
;
832 if (status
& DISCOVER_OPTS
) {
833 RxBufPtr
->OpAdds
.Status
|= DISCOVER_TYPE
;
836 if (status
& CREDENTIALS_OPT
) {
837 RxBufPtr
->OpAdds
.Status
|= CREDENTIALS_TYPE
;
848 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
851 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
860 SetMem (&RxBufPtr
->OpAdds
, sizeof RxBufPtr
->OpAdds
, 0);
864 RxBufPtr
->u
.Dhcpv4
.options
+ 4,
865 Len
- (sizeof RxBufPtr
->u
.Dhcpv4
- sizeof RxBufPtr
->u
.Dhcpv4
.options
+ 4)
868 LocalPtr
.OpPtr
= RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_OPTION_OVERLOAD_IX
- 1];
870 if ((LocalPtr
.OpPtr
) && (LocalPtr
.Overload
->Overload
& OVLD_SRVR_NAME
)) {
871 DecodeOptions (RxBufPtr
, RxBufPtr
->u
.Dhcpv4
.sname
, sizeof RxBufPtr
->u
.Dhcpv4
.sname
);
874 if (LocalPtr
.OpPtr
&& (LocalPtr
.Overload
->Overload
& OVLD_FILE
)) {
875 DecodeOptions (RxBufPtr
, RxBufPtr
->u
.Dhcpv4
.file
, sizeof RxBufPtr
->u
.Dhcpv4
.file
);
876 } else if (!RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] && RxBufPtr
->u
.Dhcpv4
.file
[0]) {
877 RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] = (DHCPV4_OP_STRUCT
*) (RxBufPtr
->u
.Dhcpv4
.file
- sizeof (DHCPV4_OP_HEADER
));
879 RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]->Header
.Length
= (UINT8
) AsciiStrLen ((CHAR8
*) RxBufPtr
->u
.Dhcpv4
.file
);
882 LocalPtr
.OpPtr
= RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_CLASS_IDENTIFIER_IX
- 1];
884 if ((LocalPtr
.OpPtr
) &&
885 LocalPtr
.PxeClassStr
->Header
.Length
>= 9 &&
886 !CompareMem (LocalPtr
.PxeClassStr
->Class
, "PXEClient", 9)
888 RxBufPtr
->OpAdds
.Status
|= PXE_TYPE
;
892 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
895 PXE_BASECODE_DEVICE
*Private
,
900 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
902 RxBufPtr
= &((DHCP_RECEIVE_BUFFER
*) Private
->DhcpPacketBuffer
)[PacketIndex
];
906 &RxBuf
[RxBufIndex
].u
.Dhcpv4
,
907 sizeof (RxBuf
[RxBufIndex
].u
.Dhcpv4
)
910 Parse (RxBufPtr
, sizeof RxBufPtr
->u
.ReceiveBuffer
);
913 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
916 PXE_BASECODE_DEVICE
*Private
,
920 Private
->EfiBc
.Mode
->ProxyOfferReceived
= TRUE
;
921 CopyParseRxBuf (Private
, RxBufIndex
, PXE_OFFER_INDEX
);
924 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
927 PXE_BASECODE_DEVICE
*Private
,
928 EFI_PXE_BASE_CODE_PACKET
*PacketPtr
,
929 EFI_PXE_BASE_CODE_PACKET
*NewPacketPtr
,
933 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
935 DhcpRxBuf
= &((DHCP_RECEIVE_BUFFER
*) Private
->DhcpPacketBuffer
)[Index
];
938 (EFI_PXE_BASE_CODE_PACKET
*) &DhcpRxBuf
->u
.Dhcpv4
,
940 sizeof (*NewPacketPtr
)
943 CopyMem (&*PacketPtr
, &*NewPacketPtr
, sizeof (*NewPacketPtr
));
945 Parse (DhcpRxBuf
, sizeof DhcpRxBuf
->u
.ReceiveBuffer
);
948 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
951 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
956 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
960 // if a DHCP type, must be DHCPOFFER and must have server id
965 (LocalPtr
.MessageType
->Type
== DHCPACK
) &&
966 DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]
970 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
973 // if a discover type packet, make sure all required fields are present
977 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
980 PXE_OP_SERVER_LIST
*BootServerOpPtr
;
983 if ((DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) == 0) {
987 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
989 if (LocalPtr
.OpPtr
== NULL
) {
990 LocalPtr
.OpPtr
= (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
991 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
994 // make sure all required fields are here
995 // if mucticast enabled, need multicast address
997 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
) &&
998 (!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
))
1002 // missing required field
1006 // if a list, it better be good
1008 BootServerOpPtr
= (PXE_OP_SERVER_LIST
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1];
1010 if (BootServerOpPtr
!= NULL
) {
1011 PXE_SERVER_LIST
*BootServerListPtr
;
1013 INTN ServerEntryLen
;
1015 BootServerListPtr
= BootServerOpPtr
->ServerList
;
1016 ServerListLen
= BootServerOpPtr
->Header
.Length
;
1019 EFI_IPv4_ADDRESS
*IpListPtr
;
1022 IpCnt
= BootServerListPtr
->u
.Ipv4List
.IpCount
;
1024 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (IpCnt
- 1) * sizeof (EFI_IPv4_ADDRESS
);
1026 if (ServerListLen
< ServerEntryLen
) {
1028 // missing required field
1033 IpListPtr
= BootServerListPtr
->u
.Ipv4List
.IpList
;
1036 if (IS_MULTICAST (IpListPtr
)) {
1038 // missing required field
1046 BootServerListPtr
= (PXE_SERVER_LIST
*) IpListPtr
;
1047 } while (ServerListLen
-= ServerEntryLen
);
1050 // else there must be a list if use list enabled or multicast and
1051 // broadcast disabled
1053 else if ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) ||
1054 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
1057 // missing required field
1062 // if not USE_BOOTFILE or no bootfile given, must have menu stuff
1064 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& USE_BOOTFILE
) ||
1065 !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1069 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_MENU_IX
- 1];
1071 if (LocalPtr
.OpPtr
== NULL
|| !DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_PROMPT_IX
- 1]) {
1073 // missing required field
1078 // make sure menu valid
1080 MenuLth
= LocalPtr
.BootMenu
->Header
.Length
;
1081 LocalPtr
.BootMenuItem
= LocalPtr
.BootMenu
->MenuItem
;
1086 MenuItemLen
= LocalPtr
.BootMenuItem
->DataLen
;
1088 if (MenuItemLen
== 0) {
1090 // missing required field
1095 MenuItemLen
+= sizeof (*LocalPtr
.BootMenuItem
) - sizeof (LocalPtr
.BootMenuItem
->Data
);
1097 MenuLth
-= MenuItemLen
;
1098 LocalPtr
.BytePtr
+= MenuItemLen
;
1099 } while (MenuLth
> 0);
1103 // missing required field
1109 if (!DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
1110 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultBootItem
;
1116 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1119 DHCP_RECEIVE_BUFFER
*RxBufPtr
1122 return (BOOLEAN
) (DHCPOfferAckEdit (RxBufPtr
) ? AckEdit (RxBufPtr
) : FALSE
);
1125 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1132 PXE_BASECODE_DEVICE
*Private
,
1133 BOOLEAN (*ExtraEdit
)(DHCP_RECEIVE_BUFFER
*DhcpRxBuf
),
1134 UINT16 OpFlags
, // for Udp read
1135 EFI_IP_ADDRESS
*ServerIpPtr
,
1136 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
1137 EFI_IP_ADDRESS
*ClientIpPtr
,
1138 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
,
1139 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
,
1140 EFI_EVENT TimeoutEvent
1143 Routine description:
1144 Wait for an OFFER/ACK packet.
1147 Private := Pointer to PxeBc interface
1148 ExtraEdit := Pointer to extra option checking function
1149 OpFlags := UdpRead() option flags
1160 EFI_IP_ADDRESS ServerIp
;
1161 EFI_STATUS StatCode
;
1166 // Wait until we get a UDP packet.
1168 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1169 RxBufLen
= sizeof RxBuf
[0].u
.ReceiveBuffer
;
1171 if ((StatCode
= UdpRead (
1180 (UINTN
*) &RxBufLen
,
1181 &DhcpRxBuf
->u
.Dhcpv4
,
1183 )) != EFI_SUCCESS
) {
1184 if (StatCode
== EFI_TIMEOUT
) {
1185 StatCode
= EFI_NO_RESPONSE
;
1191 // got a packet - see if a good offer
1193 if (DhcpRxBuf
->u
.Dhcpv4
.op
!= BOOTP_REPLY
) {
1197 if (DhcpRxBuf
->u
.Dhcpv4
.xid
!= DHCPV4_TRANSMIT_BUFFER
.xid
) {
1201 if (*(UINT32
*) DHCPV4_TRANSMIT_BUFFER
.options
!= * (UINT32
*) DhcpRxBuf
->u
.Dhcpv4
.options
) {
1205 if (*(UINT8
*) &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
> 223) {
1210 DhcpRxBuf
->u
.Dhcpv4
.chaddr
,
1211 DHCPV4_TRANSMIT_BUFFER
.chaddr
,
1212 sizeof DhcpRxBuf
->u
.Dhcpv4
.chaddr
1220 Parse (DhcpRxBuf
, RxBufLen
);
1222 if (!(*ExtraEdit
) (DhcpRxBuf
)) {
1226 // Good DHCP packet.
1228 StatCode
= EFI_SUCCESS
;
1235 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1242 PXE_BASECODE_DEVICE
*Private
1245 EFI_IP_ADDRESS ClientIp
;
1246 EFI_IP_ADDRESS ServerIp
;
1247 EFI_STATUS StatCode
;
1248 EFI_EVENT TimeoutEvent
;
1255 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1258 for (Index
= 0; Index
< (sizeof Private
->ServerCount
) / sizeof Private
->ServerCount
[0]; ++Index
) {
1259 Private
->ServerCount
[Index
] = 0;
1260 Private
->GotProxy
[Index
] = 0;
1263 Private
->GotBootp
= 0;
1265 // these we throw away
1267 Private
->GotProxy
[DHCP_ONLY_IX
] = 1;
1268 StatCode
= gBS
->CreateEvent (
1276 if (EFI_ERROR (StatCode
)) {
1280 StatCode
= gBS
->SetTimer (
1283 Private
->Timeout
* 10000000 + 1000000
1286 if (EFI_ERROR (StatCode
)) {
1287 gBS
->CloseEvent (TimeoutEvent
);
1294 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1297 DhcpRxBuf
= &RxBuf
[NumOffers
];
1300 StatCode
= GetOfferAck (
1303 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
|
1304 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
|
1305 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1318 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
1321 // check type of offer
1323 if (LocalPtr
.OpPtr
== NULL
) {
1325 // bootp - we only need one and make sure has bootfile
1327 if (Private
->GotBootp
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1331 Private
->GotBootp
= (UINT8
) (NumOffers
+ 1);
1334 // if a DHCP type, must be DHCPOFFER and must have server id
1336 else if (LocalPtr
.MessageType
->Type
!= DHCPOFFER
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]) {
1342 // get type - PXE10, WfM11a, or BINL
1344 if (DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) {
1346 } else if (DhcpRxBuf
->OpAdds
.Status
& WfM11a_TYPE
) {
1348 // WfM - make sure it has a bootfile
1350 if (!DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1356 TypeIx
= (DhcpRxBuf
->OpAdds
.Status
& PXE_TYPE
) ? BINL_IX
: DHCP_ONLY_IX
;
1359 // check DHCP or proxy
1361 if (DhcpRxBuf
->u
.Dhcpv4
.yiaddr
== 0) {
1363 // proxy - only need one of each type if not BINL
1364 // and must have at least PXE_TYPE
1366 if (TypeIx
== BINL_IX
) {
1367 Private
->BinlProxies
[Private
->GotProxy
[BINL_IX
]++] = (UINT8
) NumOffers
;
1368 } else if (Private
->GotProxy
[TypeIx
]) {
1371 Private
->GotProxy
[TypeIx
] = (UINT8
) (NumOffers
+ 1);
1374 Private
->OfferCount
[TypeIx
][Private
->ServerCount
[TypeIx
]++] = (UINT8
) NumOffers
;
1378 if (++NumOffers
== MAX_OFFERS
) {
1383 gBS
->CloseEvent (TimeoutEvent
);
1384 Private
->NumOffersReceived
= NumOffers
;
1386 return (Private
->NumOffersReceived
) ? EFI_SUCCESS
: EFI_NO_RESPONSE
;
1389 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1396 PXE_BASECODE_DEVICE
*Private
1399 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1402 PxebcMode
= Private
->EfiBc
.Mode
;
1403 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1405 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1406 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1408 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opdeclinestr
),
1409 sizeof (DHCPOpStart
) - sizeof (struct opdeclinestr
),
1412 DHCPDECLINEoptions
.DhcpMessageType
.Type
= DHCPDECLINE
;
1413 CopyMem (&DHCPDECLINEoptions
.OpDeclineEnd
, &DHCP_REQ_OPTIONS
, sizeof (DHCPDECLINEoptions
.OpDeclineEnd
));
1416 EFI_IP_ADDRESS TmpIp
;
1418 CopyMem (&TmpIp
, &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1424 &PxebcMode
->StationIp
,
1429 InitDhcpv4TxBuf (Private
);
1430 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1431 Private
->GoodStationIp
= FALSE
;
1434 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1441 PXE_BASECODE_DEVICE
*Private
1444 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1447 PxebcMode
= Private
->EfiBc
.Mode
;
1448 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1449 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1452 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opreleasestr
),
1453 sizeof (DHCPOpStart
) - sizeof (struct opreleasestr
),
1457 DHCPRELEASEoptions
.DhcpMessageType
.Type
= DHCPRELEASE
;
1460 &DHCPRELEASEoptions
.DhcServerIpPtr
,
1461 (DHCPV4_OP_SERVER_IP
*) DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1],
1462 sizeof DHCPRELEASEoptions
.DhcServerIpPtr
1465 DHCPRELEASEoptions
.End
[0] = OP_END
;
1468 EFI_IP_ADDRESS TmpIp
;
1470 CopyMem (&TmpIp
, &DHCPRELEASEoptions
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1476 &PxebcMode
->StationIp
,
1481 InitDhcpv4TxBuf (Private
);
1483 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1484 Private
->GoodStationIp
= FALSE
;
1488 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1491 PXE_BASECODE_DEVICE
*Private
,
1492 EFI_IP_ADDRESS
*ServerIpPtr
1495 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1496 EFI_STATUS StatCode
;
1497 EFI_EVENT TimeoutEvent
;
1502 StatCode
= gBS
->CreateEvent (
1510 if (EFI_ERROR (StatCode
)) {
1514 StatCode
= gBS
->SetTimer (
1517 Private
->Timeout
* 10000000 + 1000000
1520 if (EFI_ERROR (StatCode
)) {
1521 gBS
->CloseEvent (TimeoutEvent
);
1527 DhcpRxBuf
= &PXE_BINL_BUFFER
;
1530 EFI_PXE_BASE_CODE_UDP_PORT BINLSrvPort
;
1537 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1540 &Private
->EfiBc
.Mode
->StationIp
,
1541 &PSEUDO_DHCP_CLIENT_PORT
,
1548 // make sure from whom we wanted
1550 if (!DhcpRxBuf
->u
.Dhcpv4
.yiaddr
&& !CompareMem (
1552 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1553 sizeof (ServerIpPtr
->v4
)
1555 gBS
->CloseEvent (TimeoutEvent
);
1557 // got an ACK from server
1563 gBS
->CloseEvent (TimeoutEvent
);
1567 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1570 // make sure we can get BINL
1571 // send DHCPREQUEST to PXE server
1575 PXE_BASECODE_DEVICE
*Private
,
1579 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1580 EFI_IP_ADDRESS ServerIp
;
1584 DhcpRxBuf
= &RxBuf
[OfferIx
];
1587 // use next server address first.
1589 ServerIp
.Addr
[0] = DhcpRxBuf
->u
.Dhcpv4
.siaddr
;
1590 if (ServerIp
.Addr
[0] == 0) {
1592 // next server address is NULL, use option 54.
1595 ((EFI_IPv4_ADDRESS
*) &ServerIp
),
1596 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1597 sizeof (EFI_IPv4_ADDRESS
)
1602 // client IP address - filled in by client if it knows it
1605 ((EFI_IPv4_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
),
1606 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1607 sizeof (EFI_IPv4_ADDRESS
)
1610 SetMem (&DHCP_REQ_OPTIONS
, sizeof DHCP_REQ_OPTIONS
, OP_PAD
);
1611 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1612 DHCPV4_OPTIONS_BUFFER
.End
[0] = OP_END
;
1613 AddRouters (Private
, DhcpRxBuf
);
1614 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1616 for (Index
= 0; Index
< 3; Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Index
) {
1617 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
1620 // unicast DHCPREQUEST to PXE server
1625 &PseudoDhcpServerPort
,
1626 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1627 &PSEUDO_DHCP_CLIENT_PORT
1632 if (!GetBINLAck (Private
, &ServerIp
)) {
1636 // early exit failures
1637 // make sure a good ACK
1639 if (!DHCPOfferAckEdit (&PXE_BINL_BUFFER
) || (
1640 !(PXE_BINL_BUFFER
.OpAdds
.Status
& DISCOVER_TYPE
) && !PXE_BINL_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1646 Private
->EfiBc
.Mode
->ProxyOfferReceived
= TRUE
;
1650 // failed - reset seconds field, etc.
1652 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1656 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1660 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1663 PXE_BASECODE_DEVICE
*Private
,
1667 if (TryBINL (Private
, OfferIx
)) {
1671 return Release (Private
);
1674 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1676 TryFinishProxyBINL (
1677 PXE_BASECODE_DEVICE
*Private
1682 for (Index
= 0; Index
< Private
->GotProxy
[BINL_IX
]; ++Index
) {
1683 if (TryBINL (Private
, Private
->BinlProxies
[Index
])) {
1688 return Release (Private
);
1691 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1694 // try to finish DORA - send DHCP request, wait for ACK, check with ARP
1698 PXE_BASECODE_DEVICE
*Private
,
1702 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1703 EFI_IP_ADDRESS ClientIp
;
1704 EFI_IP_ADDRESS ServerIp
;
1705 EFI_STATUS StatCode
;
1707 EFI_EVENT TimeoutEvent
;
1710 // send DHCP request
1711 // if fail return false
1713 DhcpRxBuf
= &DHCPV4_ACK_BUFFER
;
1714 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
1715 CopyMem (&DHCP_REQ_OPTIONS
, &RequestOpEndStr
, sizeof (DHCP_REQ_OPTIONS
));
1716 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[OfferIx
].u
.Dhcpv4
.yiaddr
;
1719 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1720 &((DHCPV4_OP_SERVER_IP
*) RxBuf
[OfferIx
].OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1721 sizeof DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
1725 Private
->EfiBc
.Mode
->SubnetMask
.Addr
,
1731 // broadcast DHCPREQUEST
1737 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1745 StatCode
= gBS
->CreateEvent (
1753 if (EFI_ERROR (StatCode
)) {
1757 StatCode
= gBS
->SetTimer (
1760 Private
->Timeout
* 10000000 + 1000000
1763 if (EFI_ERROR (StatCode
)) {
1764 gBS
->CloseEvent (TimeoutEvent
);
1774 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
,
1785 // check type of response - need DHCPACK
1788 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1789 &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
,
1790 sizeof (EFI_IPv4_ADDRESS
)
1792 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1793 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1794 sizeof (EFI_IPv4_ADDRESS
)
1800 // check with ARP that IP unused - good return true
1802 if (!SetStationIP (Private
)) {
1804 // fail - send DHCPDECLINE and return false
1806 DeclineOffer (Private
);
1810 LocalPtr
.OpPtr
= DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1812 if (LocalPtr
.OpPtr
!= NULL
) {
1814 (EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
,
1815 &LocalPtr
.SubnetMaskStr
->Ip
,
1816 sizeof (EFI_IPv4_ADDRESS
)
1820 AddRouters (Private
, DhcpRxBuf
);
1821 gBS
->CloseEvent (TimeoutEvent
);
1825 gBS
->CloseEvent (TimeoutEvent
);
1829 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1832 // try a DHCP server of appropriate type
1836 PXE_BASECODE_DEVICE
*Private
,
1843 // go through the DHCP servers of the requested type
1845 for (Index
= 0; Index
< Private
->ServerCount
[TypeIx
]; ++Index
) {
1846 if (TryFinishDORA (Private
, Index
= Private
->OfferCount
[TypeIx
][Index
])) {
1847 if (TypeIx
== BINL_IX
&& !TryFinishBINL (Private
, Index
)) {
1858 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1861 // try a DHCP only server and a proxy of appropriate type
1864 TryProxyFinishDORA (
1865 PXE_BASECODE_DEVICE
*Private
,
1871 if (!Private
->GotProxy
[TypeIx
]) {
1873 // no proxies of the type wanted
1878 // go through the DHCP only servers
1880 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1881 if (TryFinishDORA (Private
, Private
->OfferCount
[DHCP_ONLY_IX
][Index
])) {
1882 if (TypeIx
!= BINL_IX
) {
1883 CopyProxyRxBuf (Private
, Private
->GotProxy
[TypeIx
] - 1);
1884 } else if (!TryFinishProxyBINL (Private
)) {
1886 // if didn't work with this DHCP, won't work with any
1898 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1901 // getting to the bottom of the barrel
1904 TryAnyWithBootfileFinishDORA (
1905 PXE_BASECODE_DEVICE
*Private
1909 // try a DHCP only server who has a bootfile
1914 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1917 offer
= Private
->OfferCount
[DHCP_ONLY_IX
][Index
];
1919 if (RxBuf
[offer
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] && TryFinishDORA (Private
, offer
)) {
1924 // really at bottom - see if be have any bootps
1926 if (!Private
->GotBootp
) {
1930 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[Private
->GotBootp
- 1].u
.Dhcpv4
.yiaddr
;
1932 if (!SetStationIP (Private
)) {
1936 // treat BOOTP response as DHCP ACK packet
1938 CopyParseRxBuf (Private
, Private
->GotBootp
- 1, DHCPV4_ACK_INDEX
);
1940 LocalPtr
.OpPtr
= RxBuf
[Private
->GotBootp
- 1].OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1942 if (LocalPtr
.OpPtr
!= NULL
) {
1943 *(EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
= LocalPtr
.SubnetMaskStr
->Ip
;
1949 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1955 PXE_BASECODE_DEVICE
*Private
,
1959 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
1960 EFI_STATUS StatCode
;
1963 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
| EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
;
1966 Filter
.reserved
= 0;
1969 // set filter unicast or broadcast
1971 if ((StatCode
= IpFilter (Private
, &Filter
)) != EFI_SUCCESS
) {
1975 // seed random number with hardware address
1977 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
1979 for (Private
->Timeout
= 1;
1980 Private
->Timeout
< 17;
1981 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), Private
->Timeout
<<= 1
1985 InitDhcpv4TxBuf (Private
);
1986 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
1987 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
1990 // broadcast DHCPDISCOVER
1992 StatCode
= DoUdpWrite (
1996 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2000 if (StatCode
!= EFI_SUCCESS
) {
2005 &Private
->EfiBc
.Mode
->DhcpDiscover
,
2006 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2007 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2013 if ((StatCode
= GetOffers (Private
)) != EFI_SUCCESS
) {
2014 if (StatCode
!= EFI_NO_RESPONSE
) {
2021 // select offer and reply DHCPREQUEST
2024 if (TryDHCPFinishDORA(Private
, PXE10_IX
) || // try DHCP with PXE10
2025 TryDHCPFinishDORA(Private
, WfM11a_IX
) || // no - try with WfM
2026 TryProxyFinishDORA(Private
, PXE10_IX
) || // no - try DHCP only and proxy with PXE10
2027 TryProxyFinishDORA(Private
, WfM11a_IX
) || // no - try DHCP only and proxy with WfM
2028 TryDHCPFinishDORA(Private
, BINL_IX
) || // no - try with WfM
2029 TryProxyFinishDORA(Private
, BINL_IX
) || // no - try DHCP only and proxy with PXE10
2030 TryAnyWithBootfileFinishDORA(Private
))
2040 NumOffers
= Private
->NumOffersReceived
;
2042 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2046 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
) {
2050 // check if a bootp server
2052 if (!RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1]) {
2054 // it is - just check ARP
2056 if (!SetStationIP (Private
)) {
2061 // else check if a DHCP only server
2063 else if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
))) {
2065 // it is a normal DHCP offer (without any PXE options), just finish the D.O.R.A by sending DHCP request.
2067 if (!TryFinishDORA (Private
, Index
)) {
2070 } else if (TryFinishDORA (Private
, Index
)) {
2071 if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) && !TryFinishBINL (Private
, Index
)) {
2076 DEBUG ((DEBUG_WARN
, "\nDoDhcpDora() Got packets. "));
2080 // now look for DHCP onlys and a Proxy
2082 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2086 // ignore proxies, bootps, non DHCP onlys, and bootable DHCPS
2088 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
||
2089 !RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1] ||
2090 RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
) ||
2091 RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
2096 // found non bootable DHCP only - try to find a proxy
2098 for (Index2
= 0; Index2
< NumOffers
; ++Index2
) {
2099 if (!RxBuf
[Index2
].u
.Dhcpv4
.yiaddr
) {
2100 if (!TryFinishDORA (Private
, Index
)) {
2107 if (RxBuf
[Index2
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) {
2108 CopyProxyRxBuf (Private
, Index2
);
2109 } else if (!TryFinishBINL (Private
, Index2
)) {
2113 DEBUG ((DEBUG_WARN
, "\nDoDhcpDora() Got packets. "));
2120 return EFI_NO_RESPONSE
;
2123 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2126 // determine if the server ip is in the ip list
2130 EFI_IP_ADDRESS
*ServerIpPtr
,
2131 PXE_SERVER_LISTS
*ServerListPtr
2136 if (!ServerListPtr
|| !ServerListPtr
->Ipv4List
.IpCount
) {
2140 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2143 &ServerListPtr
->Ipv4List
.IpList
[Index
],
2144 sizeof (EFI_IPv4_ADDRESS
)
2153 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2155 ExtractBootServerList (
2157 DHCPV4_OP_STRUCT
*ptr
,
2158 PXE_SERVER_LISTS
**ServerListPtr
2164 LocalPtr
.OpPtr
= ptr
;
2165 ServerListLen
= LocalPtr
.BootServersStr
->Header
.Length
;
2170 LocalPtr
.BootServerList
= LocalPtr
.BootServersStr
->ServerList
;
2172 while (ServerListLen
) {
2173 INTN ServerEntryLen
;
2175 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (LocalPtr
.BootServerList
->u
.Ipv4List
.IpCount
- 1) *
2176 sizeof (EFI_IPv4_ADDRESS
);
2178 if (NTOHS (LocalPtr
.BootServerList
->Type
) == Type
) {
2179 *ServerListPtr
= &LocalPtr
.BootServerList
->u
;
2183 (LocalPtr
.BytePtr
) += ServerEntryLen
;
2184 ServerListLen
-= ServerEntryLen
;
2190 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2193 PXE_BASECODE_DEVICE
*Private
2196 if (Private
->TransmitBuffer
!= NULL
) {
2197 gBS
->FreePool (Private
->TransmitBuffer
);
2198 Private
->TransmitBuffer
= NULL
;
2201 if (Private
->ReceiveBuffers
!= NULL
) {
2202 gBS
->FreePool (Private
->ReceiveBuffers
);
2203 Private
->ReceiveBuffers
= NULL
;
2207 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2210 PXE_BASECODE_DEVICE
*Private
2215 if (Private
->DhcpPacketBuffer
== NULL
) {
2216 Status
= gBS
->AllocatePool (
2217 EfiBootServicesData
,
2218 sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1),
2219 &Private
->DhcpPacketBuffer
2222 if (EFI_ERROR (Status
) || Private
->DhcpPacketBuffer
== NULL
) {
2223 Private
->DhcpPacketBuffer
= NULL
;
2229 Status
= gBS
->AllocatePool (
2230 EfiBootServicesData
,
2231 sizeof (EFI_PXE_BASE_CODE_PACKET
),
2232 &Private
->TransmitBuffer
2235 if (EFI_ERROR (Status
) || Private
->TransmitBuffer
== NULL
) {
2236 gBS
->FreePool (Private
->DhcpPacketBuffer
);
2237 Private
->DhcpPacketBuffer
= NULL
;
2238 Private
->TransmitBuffer
= NULL
;
2243 Status
= gBS
->AllocatePool (
2244 EfiBootServicesData
,
2245 sizeof (DHCP_RECEIVE_BUFFER
) * (MAX_OFFERS
),
2246 &Private
->ReceiveBuffers
2249 if (EFI_ERROR (Status
) || Private
->ReceiveBuffers
== NULL
) {
2250 gBS
->FreePool (Private
->TransmitBuffer
);
2251 gBS
->FreePool (Private
->DhcpPacketBuffer
);
2252 Private
->DhcpPacketBuffer
= NULL
;
2253 Private
->TransmitBuffer
= NULL
;
2254 Private
->ReceiveBuffers
= NULL
;
2262 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2271 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2272 IN BOOLEAN SortOffers
2275 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
2276 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2277 PXE_BASECODE_DEVICE
*Private
;
2278 EFI_STATUS StatCode
;
2281 // Lock the instance data and make sure started
2283 StatCode
= EFI_SUCCESS
;
2286 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
2287 return EFI_INVALID_PARAMETER
;
2290 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2292 if (Private
== NULL
) {
2293 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
2294 return EFI_INVALID_PARAMETER
;
2297 EfiAcquireLock (&Private
->Lock
);
2299 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2300 DEBUG ((DEBUG_ERROR
, "BC was not started."));
2301 EfiReleaseLock (&Private
->Lock
);
2302 return EFI_NOT_STARTED
;
2305 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
;
2307 Filter
.reserved
= 0;
2309 DEBUG ((DEBUG_INFO
, "\nBcDhcp() Enter. "));
2311 PxebcMode
= Private
->EfiBc
.Mode
;
2313 if (!GetMem (Private
)) {
2314 DEBUG ((DEBUG_ERROR
, "\nBcDhcp() GetMem() failed.\n"));
2315 EfiReleaseLock (&Private
->Lock
);
2316 return EFI_OUT_OF_RESOURCES
;
2319 PxebcMode
->DhcpDiscoverValid
= FALSE
;
2320 PxebcMode
->DhcpAckReceived
= FALSE
;
2321 PxebcMode
->ProxyOfferReceived
= FALSE
;
2323 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
2328 if (Private
->TotalSeconds
== 0) {
2330 // put in seconds field of DHCP send packets
2332 Private
->TotalSeconds
= 4;
2335 if ((StatCode
= DoDhcpDora (Private
, SortOffers
)) == EFI_SUCCESS
) {
2337 // success - copy packets
2339 PxebcMode
->DhcpDiscoverValid
= PxebcMode
->DhcpAckReceived
= TRUE
;
2342 &PxebcMode
->DhcpAck
,
2343 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_ACK_PACKET
,
2344 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2347 if (PxebcMode
->ProxyOfferReceived
) {
2349 &PxebcMode
->ProxyOffer
,
2350 (EFI_PXE_BASE_CODE_PACKET
*) &PXE_OFFER_PACKET
,
2351 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2356 // set filter back to unicast
2358 IpFilter (Private
, &Filter
);
2363 // Unlock the instance data
2365 DEBUG ((DEBUG_WARN
, "\nBcDhcp() Exit = %xh ", StatCode
));
2367 EfiReleaseLock (&Private
->Lock
);
2371 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2373 VerifyCredentialOption (
2381 // Fail verification if either pointer is NULL.
2383 if (tx
== NULL
|| rx
== NULL
) {
2387 // Fail verification if tx[0] is not a credential type option
2388 // or if the length is zero or not a multiple of four.
2390 if (tx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| tx
[1] == 0 || tx
[1] % 4 != 0) {
2394 // Fail verification if rx[0] is not a credential type option
2395 // or if the length is not equal to four.
2397 if (rx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| rx
[1] != 4) {
2401 // Look through transmitted credential types for a copy
2402 // of the received credential type.
2404 for (n
= 0; n
< tx
[1]; n
+= 4) {
2405 if (!CompareMem (&tx
[n
+ 2], &rx
[2], 4)) {
2413 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2421 PXE_BASECODE_DEVICE
*Private
,
2424 IN UINT16
*LayerPtr
,
2426 EFI_IP_ADDRESS
*DestPtr
,
2427 PXE_SERVER_LISTS
*ServerListPtr
2430 EFI_PXE_BASE_CODE_UDP_PORT ClientPort
;
2431 EFI_PXE_BASE_CODE_UDP_PORT ServerPort
;
2432 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2433 EFI_STATUS StatCode
;
2434 EFI_EVENT TimeoutEvent
;
2437 PxebcMode
= Private
->EfiBc
.Mode
;
2439 if (DestPtr
->Addr
[0] == 0) {
2440 DEBUG ((DEBUG_WARN
, "\nDoDiscover() !DestPtr->Addr[0]"));
2441 return EFI_INVALID_PARAMETER
;
2444 // seed random number with hardware address
2446 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2448 if (DestPtr
->Addr
[0] == BroadcastIP
.Addr
[0]) {
2449 ClientPort
= DHCPClientPort
;
2450 ServerPort
= DhcpServerPort
;
2452 ClientPort
= PSEUDO_DHCP_CLIENT_PORT
;
2453 ServerPort
= PseudoDhcpServerPort
;
2457 *LayerPtr
|= PXE_BOOT_LAYER_CREDENTIAL_FLAG
;
2459 *LayerPtr
&= PXE_BOOT_LAYER_MASK
;
2462 for (Private
->Timeout
= 1;
2463 Private
->Timeout
< 5;
2464 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Private
->Timeout
2466 InitDhcpv4TxBuf (Private
);
2468 // initialize DHCP message structure
2470 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2471 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2473 &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2474 &PxebcMode
->StationIp
,
2475 sizeof DHCPV4_TRANSMIT_BUFFER
.ciaddr
2478 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
2479 DISCOVERoptions
.Header
.OpCode
= OP_VENDOR_SPECIFIC
;
2480 DISCOVERoptions
.BootItem
.Header
.OpCode
= VEND_PXE_BOOT_ITEM
;
2481 DISCOVERoptions
.BootItem
.Header
.Length
= DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM
);
2482 DISCOVERoptions
.BootItem
.Type
= HTONS (Type
);
2483 DISCOVERoptions
.BootItem
.Layer
= HTONS (*LayerPtr
);
2486 EFI_BIS_PROTOCOL
*BisPtr
;
2487 BIS_APPLICATION_HANDLE BisAppHandle
;
2488 EFI_BIS_DATA
*BisDataSigInfo
;
2489 EFI_BIS_SIGNATURE_INFO
*BisSigInfo
;
2493 BisPtr
= PxebcBisStart (
2499 if (BisPtr
== NULL
) {
2501 // %%TBD - In order to get here, BIS must have
2502 // been present when PXEBC.Start() was called.
2503 // BIS had to be shutdown/removed/damaged
2504 // before PXEBC.Discover() was called.
2505 // Do we need to document a specific error
2508 return EFI_OUT_OF_RESOURCES
;
2511 // Compute number of credential types.
2513 Index2
= BisDataSigInfo
->Length
/ sizeof (EFI_BIS_SIGNATURE_INFO
);
2515 DISCREDoptions
.Header
.OpCode
= VEND_PXE_CREDENTIAL_TYPES
;
2517 DISCREDoptions
.Header
.Length
= (UINT8
) (Index2
* sizeof (PXE_CREDENTIAL
));
2519 OpLen
= (UINT8
) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
) + sizeof (DHCPV4_OP_HEADER
) + DISCREDoptions
.Header
.Length
);
2521 BisSigInfo
= (EFI_BIS_SIGNATURE_INFO
*) BisDataSigInfo
->Data
;
2523 for (Index
= 0; Index
< Index2
; ++Index
) {
2526 CopyMem (&x
, &BisSigInfo
[Index
], sizeof x
);
2528 CopyMem (&DISCREDoptions
.Credentials
[Index
], &x
, sizeof x
);
2531 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
2533 OpLen
= DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
);
2536 DISCOVERoptions
.Header
.Length
= OpLen
;
2538 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
- 1] = OP_END
;
2539 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
] = OP_END
;
2541 StatCode
= DoUdpWrite (
2545 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2549 if (StatCode
!= EFI_SUCCESS
) {
2555 StatCode
= gBS
->CreateEvent (
2563 if (EFI_ERROR (StatCode
)) {
2567 StatCode
= gBS
->SetTimer (
2570 Private
->Timeout
* 10000000 + 1000000
2573 if (EFI_ERROR (StatCode
)) {
2574 gBS
->CloseEvent (TimeoutEvent
);
2581 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
2585 RxBufPtr
= UseBis
? &PXE_BIS_BUFFER
: &PXE_ACK_BUFFER
;
2586 ZeroMem (&Private
->ServerIp
, sizeof (EFI_IP_ADDRESS
));
2592 (EFI_IP_ADDRESS
*) &Private
->ServerIp
,
2594 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2602 // check type of response - need PXEClient DHCPACK of proper type with bootfile
2604 if (!(RxBufPtr
->OpAdds
.Status
& PXE_TYPE
) ||
2605 (UseBis
&& (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
)) ||
2606 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] ||
2607 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1] ||
2608 !InServerList((EFI_IP_ADDRESS
*)&((DHCPV4_OP_SERVER_IP
*)RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
-1])->Ip
, ServerListPtr
)) {
2613 TmpType
= TmpLayer
= 0;
2615 if (RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
2616 TmpType
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Type
);
2618 if (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
) {
2619 TmpLayer
= (UINT16
) (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
>> 8);
2621 TmpLayer
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
);
2625 if (TmpType
!= Type
) {
2630 if (!RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]) {
2634 if (!VerifyCredentialOption (
2635 (UINT8
*) &DISCREDoptions
.Header
,
2636 (UINT8
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]
2642 *LayerPtr
= TmpLayer
;
2646 &PxebcMode
->PxeBisReply
,
2647 &RxBufPtr
->u
.Dhcpv4
,
2648 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2651 PxebcMode
->PxeBisReplyReceived
= TRUE
;
2653 StatCode
= DoDiscover (
2655 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2663 gBS
->CloseEvent (TimeoutEvent
);
2667 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= TRUE
;
2670 &PxebcMode
->PxeDiscover
,
2671 &*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2672 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
)
2676 &PxebcMode
->PxeReply
,
2677 &*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
,
2678 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
)
2681 AddRouters (Private
, RxBufPtr
);
2683 gBS
->CloseEvent (TimeoutEvent
);
2687 gBS
->CloseEvent (TimeoutEvent
);
2695 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2699 Private := Pointer to PxeBc interface
2704 McastServerListPtr :=
2711 PXE_BASECODE_DEVICE
*Private
,
2713 IN UINT16
*LayerPtr
,
2715 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*DiscoverInfoPtr
,
2716 PXE_SERVER_LISTS
*McastServerListPtr
,
2717 PXE_SERVER_LISTS
*ServerListPtr
2720 EFI_IP_ADDRESS DestIp
;
2721 EFI_STATUS StatCode
;
2723 DEBUG ((DEBUG_INFO
, "\nDiscover() Type=%d Layer=%d ", Type
, *LayerPtr
));
2726 DEBUG ((DEBUG_INFO
, "BIS "));
2729 // get dest IP addr - mcast, bcast, or unicast
2731 if (DiscoverInfoPtr
->UseMCast
) {
2732 DestIp
.v4
= DiscoverInfoPtr
->ServerMCastIp
.v4
;
2736 "\nDiscover() MCast %d.%d.%d.%d ",
2743 if ((StatCode
= DoDiscover (
2745 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2751 )) != EFI_TIMEOUT
) {
2754 "\nDiscover() status == %r (%Xh)",
2763 if (DiscoverInfoPtr
->UseBCast
) {
2764 DEBUG ((DEBUG_INFO
, "\nDiscver() BCast "));
2766 if ((StatCode
= DoDiscover (
2768 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2774 )) != EFI_TIMEOUT
) {
2776 DEBUG ((DEBUG_WARN
, "\nDiscover() status == %r (%Xh)", StatCode
, StatCode
));
2782 if (DiscoverInfoPtr
->UseUCast
) {
2787 "\nDiscover() UCast IP#=%d ",
2788 ServerListPtr
->Ipv4List
.IpCount
)
2791 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2792 CopyMem (&DestIp
, &ServerListPtr
->Ipv4List
.IpList
[Index
], 4);
2796 "\nDiscover() UCast %d.%d.%d.%d ",
2803 if ((StatCode
= DoDiscover (
2805 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2811 )) != EFI_TIMEOUT
) {
2814 "\nDiscover() status == %r (%Xh)",
2824 DEBUG ((DEBUG_WARN
, "\nDiscover() TIMEOUT"));
2829 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2841 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
2843 IN UINT16
*LayerPtr
,
2845 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
* DiscoverInfoPtr OPTIONAL
2848 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
2849 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2850 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
2851 PXE_SERVER_LISTS DefaultSrvList
;
2852 PXE_SERVER_LISTS
*ServerListPtr
;
2853 PXE_SERVER_LISTS
*McastServerListPtr
;
2857 BOOLEAN AcquiredSrvList
;
2858 EFI_STATUS StatCode
;
2859 PXE_BASECODE_DEVICE
*Private
;
2862 // Lock the instance data and make sure started
2864 StatCode
= EFI_SUCCESS
;
2867 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
2868 return EFI_INVALID_PARAMETER
;
2871 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2873 if (Private
== NULL
) {
2874 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2875 return EFI_INVALID_PARAMETER
;
2878 EfiAcquireLock (&Private
->Lock
);
2880 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2881 DEBUG ((DEBUG_ERROR
, "BC was not started."));
2882 EfiReleaseLock (&Private
->Lock
);
2883 return EFI_NOT_STARTED
;
2886 ServerListPtr
= NULL
;
2887 McastServerListPtr
= NULL
;
2888 AcquiredSrvList
= FALSE
;
2890 PxebcMode
= Private
->EfiBc
.Mode
;
2892 if (!GetMem (Private
)) {
2893 EfiReleaseLock (&Private
->Lock
);
2894 return EFI_OUT_OF_RESOURCES
;
2898 if (!PxebcMode
->BisSupported
) {
2899 EfiReleaseLock (&Private
->Lock
);
2900 return EFI_INVALID_PARAMETER
;
2904 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
2906 if (Private
->TotalSeconds
== 0) {
2908 // put in seconds field of DHCP send packets
2910 Private
->TotalSeconds
= 4;
2913 ZeroMem (&DefaultInfo
, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO
));
2916 // if layer number not zero, use previous discover
2918 if (*LayerPtr
!= 0) {
2919 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0"));
2921 if (DiscoverInfoPtr
!= NULL
) {
2922 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n"));
2924 EfiReleaseLock (&Private
->Lock
);
2925 return EFI_INVALID_PARAMETER
;
2928 if (!PxebcMode
->PxeDiscoverValid
) {
2929 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n"));
2931 EfiReleaseLock (&Private
->Lock
);
2932 return EFI_INVALID_PARAMETER
;
2935 if (!PxebcMode
->PxeReplyReceived
) {
2936 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n"));
2938 EfiReleaseLock (&Private
->Lock
);
2939 return EFI_INVALID_PARAMETER
;
2942 if (UseBis
&& !PxebcMode
->PxeBisReplyReceived
) {
2943 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n"));
2945 EfiReleaseLock (&Private
->Lock
);
2946 return EFI_INVALID_PARAMETER
;
2949 DefaultInfo
.UseUCast
= TRUE
;
2950 DiscoverInfoPtr
= &DefaultInfo
;
2952 DefaultSrvList
.Ipv4List
.IpCount
= 1;
2953 CopyMem (&DefaultSrvList
.Ipv4List
.IpList
[0], &Private
->ServerIp
, 4);
2955 ServerListPtr
= &DefaultSrvList
;
2958 // layer is zero - see if info is supplied or if we need to use info from a cached offer
2960 else if (!DiscoverInfoPtr
) {
2962 // not supplied - generate it
2963 // make sure that there is cached, appropriate information
2964 // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail
2966 DhcpRxBuf
= (PxebcMode
->ProxyOfferReceived
) ? &PXE_OFFER_BUFFER
: &DHCPV4_ACK_BUFFER
;
2968 if (!PxebcMode
->DhcpAckReceived
|| !(DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
)) {
2969 DEBUG ((DEBUG_WARN
, "\nBcDiscover() !ack && !proxy"));
2970 EfiReleaseLock (&Private
->Lock
);
2971 return EFI_INVALID_PARAMETER
;
2974 DiscoverInfoPtr
= &DefaultInfo
;
2976 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
2979 // if multicast enabled, need multicast address
2981 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
)) {
2982 DefaultInfo
.UseMCast
= TRUE
;
2985 ((EFI_IPv4_ADDRESS
*) &DefaultInfo
.ServerMCastIp
),
2986 &((DHCPV4_OP_IP_ADDRESS
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1])->Ip
,
2987 sizeof (EFI_IPv4_ADDRESS
)
2991 DefaultInfo
.UseBCast
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_BCAST
) == 0);
2993 DefaultInfo
.MustUseList
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) != 0);
2995 DefaultInfo
.UseUCast
= (BOOLEAN
)
2997 (DefaultInfo
.MustUseList
) ||
2998 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
3001 if ((DefaultInfo
.UseUCast
| DefaultInfo
.MustUseList
) && !ExtractBootServerList (
3003 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1],
3006 DEBUG ((DEBUG_WARN
, "\nBcDiscover() type not in list"));
3007 EfiReleaseLock (&Private
->Lock
);
3008 return EFI_INVALID_PARAMETER
;
3012 // Info supplied - make SrvList if required
3013 // if we use ucast discovery or must use list, there better be one
3015 else if (DiscoverInfoPtr
->UseUCast
|| DiscoverInfoPtr
->MustUseList
) {
3017 // there better be a list
3019 if (DiscoverInfoPtr
->IpCnt
== 0) {
3020 DEBUG ((DEBUG_WARN
, "\nBcDiscover() no bootserver list"));
3021 EfiReleaseLock (&Private
->Lock
);
3022 return EFI_INVALID_PARAMETER
;
3027 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3028 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3029 if (DiscoverInfoPtr
->SrvList
[Index
].AcceptAnyResponse
) {
3031 DEBUG ((DEBUG_WARN
, "\nBcDiscover() accept any?"));
3032 EfiReleaseLock (&Private
->Lock
);
3033 return EFI_INVALID_PARAMETER
;
3036 DefaultSrvList
.Ipv4List
.IpCount
= 0;
3037 ServerListPtr
= &DefaultSrvList
;
3047 DEBUG ((DEBUG_WARN
, "\nBcDiscover() !Index2?"));
3048 EfiReleaseLock (&Private
->Lock
);
3049 return EFI_INVALID_PARAMETER
;
3052 if (ServerListPtr
== NULL
) {
3053 ServerListPtr
= AllocatePool (
3054 sizeof (PXEV4_SERVER_LIST
) + (Index2
- 1) * sizeof (EFI_IPv4_ADDRESS
)
3057 if (ServerListPtr
== NULL
) {
3058 EfiReleaseLock (&Private
->Lock
);
3059 return EFI_OUT_OF_RESOURCES
;
3062 // build an array of IP addresses from the server list
3064 AcquiredSrvList
= TRUE
;
3065 ServerListPtr
->Ipv4List
.IpCount
= (UINT8
) Index2
;
3067 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3068 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3070 &ServerListPtr
->Ipv4List
.IpList
[Index2
++],
3071 &DiscoverInfoPtr
->SrvList
[Index
].IpAddr
.v4
,
3072 sizeof ServerListPtr
->Ipv4List
.IpList
[0]
3079 if (DiscoverInfoPtr
->MustUseList
) {
3080 McastServerListPtr
= ServerListPtr
;
3083 if (!(DiscoverInfoPtr
->UseMCast
|| DiscoverInfoPtr
->UseBCast
|| DiscoverInfoPtr
->UseUCast
)) {
3084 DEBUG ((DEBUG_WARN
, "\nBcDiscover() Nothing to use!\n"));
3086 EfiReleaseLock (&Private
->Lock
);
3087 return EFI_INVALID_PARAMETER
;
3090 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= PxebcMode
->PxeBisReplyReceived
= FALSE
;
3092 StatCode
= Discover (
3102 if (AcquiredSrvList
) {
3103 gBS
->FreePool (ServerListPtr
);
3109 // Unlock the instance data
3113 "\nBcDiscover() status == %r (%Xh)\n",
3118 EfiReleaseLock (&Private
->Lock
);
3122 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3131 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
3132 BOOLEAN
*NewDhcpDiscoverValid
, OPTIONAL
3133 BOOLEAN
*NewDhcpAckReceived
, OPTIONAL
3134 BOOLEAN
*NewProxyOfferReceived
, OPTIONAL
3135 BOOLEAN
*NewPxeDiscoverValid
, OPTIONAL
3136 BOOLEAN
*NewPxeReplyReceived
, OPTIONAL
3137 BOOLEAN
*NewPxeBisReplyReceived
, OPTIONAL
3138 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
3139 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
3140 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
3141 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
3142 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
3143 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
3146 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
3148 PXE_BASECODE_DEVICE
*Private
;
3151 // Lock the instance data and make sure started
3155 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
3156 return EFI_INVALID_PARAMETER
;
3159 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
3161 if (Private
== NULL
) {
3162 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
3163 return EFI_INVALID_PARAMETER
;
3166 EfiAcquireLock (&Private
->Lock
);
3168 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
3169 DEBUG ((DEBUG_ERROR
, "BC was not started."));
3170 EfiReleaseLock (&Private
->Lock
);
3171 return EFI_NOT_STARTED
;
3174 PxebcMode
= Private
->EfiBc
.Mode
;
3176 if (Private
->DhcpPacketBuffer
== NULL
) {
3177 Status
= gBS
->AllocatePool (
3178 EfiBootServicesData
,
3179 sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1),
3180 &Private
->DhcpPacketBuffer
3183 if (EFI_ERROR (Status
) || Private
->DhcpPacketBuffer
== NULL
) {
3184 Private
->DhcpPacketBuffer
= NULL
;
3185 EfiReleaseLock (&Private
->Lock
);
3186 return EFI_OUT_OF_RESOURCES
;
3195 Private
->FileSize
= 0;
3196 if (NewDhcpDiscoverValid
!= NULL
) {
3197 PxebcMode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
3200 if (NewDhcpAckReceived
!= NULL
) {
3201 PxebcMode
->DhcpAckReceived
= *NewDhcpAckReceived
;
3204 if (NewProxyOfferReceived
!= NULL
) {
3205 PxebcMode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
3208 if (NewPxeDiscoverValid
!= NULL
) {
3209 PxebcMode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
3212 if (NewPxeReplyReceived
!= NULL
) {
3213 PxebcMode
->PxeReplyReceived
= *NewPxeReplyReceived
;
3216 if (NewPxeBisReplyReceived
!= NULL
) {
3217 PxebcMode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
3220 if (NewDhcpDiscover
!= NULL
) {
3222 &PxebcMode
->DhcpDiscover
,
3224 sizeof *NewDhcpDiscover
3228 if (NewDhcpAck
!= NULL
) {
3229 CopyParse (Private
, &PxebcMode
->DhcpAck
, NewDhcpAck
, DHCPV4_ACK_INDEX
);
3232 if (NewProxyOffer
!= NULL
) {
3233 CopyParse (Private
, &PxebcMode
->ProxyOffer
, NewProxyOffer
, PXE_OFFER_INDEX
);
3236 if (NewPxeDiscover
!= NULL
) {
3238 &PxebcMode
->PxeDiscover
,
3240 sizeof *NewPxeDiscover
3244 if (NewPxeReply
!= NULL
) {
3245 CopyParse (Private
, &PxebcMode
->PxeReply
, NewPxeReply
, PXE_ACK_INDEX
);
3248 if (NewPxeBisReply
!= NULL
) {
3249 CopyParse (Private
, &PxebcMode
->PxeBisReply
, NewPxeBisReply
, PXE_BIS_INDEX
);
3252 // Unlock the instance data
3254 EfiReleaseLock (&Private
->Lock
);
3258 /* eof - pxe_bc_dhcp.c */