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 STATIC EFI_PXE_BASE_CODE_UDP_PORT DhcpServerPort
= DHCP_SERVER_PORT
;
26 STATIC EFI_PXE_BASE_CODE_UDP_PORT DHCPClientPort
= DHCP_CLIENT_PORT
;
27 STATIC EFI_PXE_BASE_CODE_UDP_PORT PseudoDhcpServerPort
= PXE_DISCOVERY_PORT
;
28 #define PSEUDO_DHCP_CLIENT_PORT PseudoDhcpServerPort
29 STATIC EFI_IP_ADDRESS BroadcastIP
= {{0xffffffff}};
30 STATIC 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 STATIC
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 STATIC 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
123 STATIC
struct optionsstr
{
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 STATIC 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 STATIC 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_STRUCTURE_TABLE
*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_HEADER
*) (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
533 PXE_BASECODE_DEVICE
*Private
,
534 DHCPV4_OP_IP_LIST
*IpListPtr
537 EFI_IP_ADDRESS TmpIp
;
541 if (IpListPtr
== NULL
) {
545 for (Index
= 0, num
= IpListPtr
->Header
.Length
>> 2; Index
< num
; ++Index
) {
546 CopyMem (&TmpIp
, &IpListPtr
->IpList
[Index
], 4);
547 Ip4AddRouter (Private
, &TmpIp
);
551 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
554 // send ARP for our IP - fail if someone has it
559 PXE_BASECODE_DEVICE
*Private
562 EFI_MAC_ADDRESS DestMac
;
563 EFI_STATUS EfiStatus
;
565 ZeroMem (&DestMac
, sizeof DestMac
);
567 if (GetHwAddr(Private
, (EFI_IP_ADDRESS
*)&DHCP_REQ_OPTIONS
.OpReqIP
.Ip
, (EFI_MAC_ADDRESS
*)&DestMac
)
568 || DoArp(Private
, (EFI_IP_ADDRESS
*)&DHCP_REQ_OPTIONS
.OpReqIP
.Ip
, (EFI_MAC_ADDRESS
*)&DestMac
) == EFI_SUCCESS
) {
569 return FALSE
; // somebody else has this IP
573 (EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->StationIp
,
574 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
575 sizeof (EFI_IPv4_ADDRESS
)
578 Private
->GoodStationIp
= TRUE
;
580 if (!Private
->UseIgmpv1Reporting
) {
584 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
588 EfiStatus
= gBS
->CreateEvent (
593 &Private
->Igmpv1TimeoutEvent
596 if (EFI_ERROR (EfiStatus
)) {
597 Private
->Igmpv1TimeoutEvent
= NULL
;
601 EfiStatus
= gBS
->SetTimer (
602 Private
->Igmpv1TimeoutEvent
,
604 (UINT64
) V1ROUTER_PRESENT_TIMEOUT
* 10000000
607 if (EFI_ERROR (EfiStatus
)) {
608 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
609 Private
->Igmpv1TimeoutEvent
= NULL
;
615 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
619 PXE_BASECODE_DEVICE
*Private
,
620 DHCP_RECEIVE_BUFFER
*RxBufPtr
625 (DHCPV4_OP_IP_LIST
*) RxBufPtr
->OpAdds
.PktOptAdds
[OP_ROUTER_LIST_IX
- 1]
629 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
633 PXE_BASECODE_DEVICE
*Private
,
634 EFI_IP_ADDRESS
*ServerIpPtr
,
635 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
636 EFI_IP_ADDRESS
*ClientIpPtr
,
637 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
642 Len
= sizeof DHCPV4_TRANSMIT_BUFFER
;
646 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
655 Private
->TransmitBuffer
659 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
662 // initialize the DHCP structure
671 PXE_BASECODE_DEVICE
*Private
676 CHAR8
*SystemSerialNumber
;
677 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
679 PxebcMode
= Private
->EfiBc
.Mode
;
681 ZeroMem (&DHCPV4_TRANSMIT_BUFFER
, sizeof (DHCPV4_STRUCT
));
682 DHCPV4_TRANSMIT_BUFFER
.op
= BOOTP_REQUEST
;
683 DHCPV4_TRANSMIT_BUFFER
.htype
= Private
->SimpleNetwork
->Mode
->IfType
;
684 DHCPV4_TRANSMIT_BUFFER
.flags
= HTONS (DHCP_BROADCAST_FLAG
);
685 CopyMem (&DHCPV4_OPTIONS_BUFFER
, (VOID
*) &DHCPOpStart
, sizeof (DHCPOpStart
));
688 // default to hardware address
690 HwAddrLen
= Private
->SimpleNetwork
->Mode
->HwAddressSize
;
692 if (HwAddrLen
> sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
) {
693 HwAddrLen
= sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
;
696 String
= (UINT8
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
;
698 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
699 (EFI_GUID
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
,
702 if (PxebcMode
->SendGUID
) {
703 HwAddrLen
= sizeof (EFI_GUID
);
704 String
= (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
;
708 // GUID not yet set - send all 0xff's to show programable (via SetVariable)
709 // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);
710 // GUID not yet set - send all 0's to show not programable
712 ZeroMem (DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
, sizeof (EFI_GUID
));
715 DHCPV4_TRANSMIT_BUFFER
.hlen
= (UINT8
) HwAddrLen
;
716 CopyMem (DHCPV4_TRANSMIT_BUFFER
.chaddr
, String
, HwAddrLen
);
720 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
,
721 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
724 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.Type
= Private
->NiiPtr
->Type
;
725 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
= Private
->NiiPtr
->MajorVer
;
726 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
= Private
->NiiPtr
->MinorVer
;
728 *(C4Str
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.InterfaceName
= *(C4Str
*) Private
->NiiPtr
->StringId
;
731 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
,
732 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
,
733 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
737 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
,
738 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
,
739 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
743 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
747 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
760 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
773 LocalPtr
.BytePtr
= ptr
;
774 if (Op
<= MAX_OUR_PXE_OPT
) {
775 Index
= ourPXEopts
[Op
- 1];
777 RxBufPtr
->OpAdds
.PxeOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
778 status
|= 1 << Index
;
779 if (Index
== VEND_PXE_BOOT_ITEM
&& LocalPtr
.BootItem
->Header
.Length
== 3) {
780 RxBufPtr
->OpAdds
.Status
|= USE_THREE_BYTE
;
791 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
795 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
805 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
818 LocalPtr
.BytePtr
= ptr
;
819 if (Op
<= MAX_OUR_OPT
) {
820 Index
= OurDhcpOptions
[Op
- 1];
822 RxBufPtr
->OpAdds
.PktOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
823 if (Index
== OP_VENDOR_SPECIFIC_IX
) {
825 status
= DecodePxeOptions (
827 (UINT8
*) LocalPtr
.VendorOptions
->VendorOptions
,
828 LocalPtr
.VendorOptions
->Header
.Length
831 RxBufPtr
->OpAdds
.Status
|= PXE_TYPE
;
833 // check for all the MTFTP info options present - any missing is a nogo
835 if ((status
& WfM11a_OPTS
) == WfM11a_OPTS
) {
836 RxBufPtr
->OpAdds
.Status
|= WfM11a_TYPE
;
839 if (status
& DISCOVER_OPTS
) {
840 RxBufPtr
->OpAdds
.Status
|= DISCOVER_TYPE
;
843 if (status
& CREDENTIALS_OPT
) {
844 RxBufPtr
->OpAdds
.Status
|= CREDENTIALS_TYPE
;
855 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
858 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
867 SetMem (&RxBufPtr
->OpAdds
, sizeof RxBufPtr
->OpAdds
, 0);
871 RxBufPtr
->u
.Dhcpv4
.options
+ 4,
872 Len
- (sizeof RxBufPtr
->u
.Dhcpv4
- sizeof RxBufPtr
->u
.Dhcpv4
.options
+ 4)
875 LocalPtr
.OpPtr
= RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_OPTION_OVERLOAD_IX
- 1];
877 if ((LocalPtr
.OpPtr
) && (LocalPtr
.Overload
->Overload
& OVLD_SRVR_NAME
)) {
878 DecodeOptions (RxBufPtr
, RxBufPtr
->u
.Dhcpv4
.sname
, sizeof RxBufPtr
->u
.Dhcpv4
.sname
);
881 if (LocalPtr
.OpPtr
&& (LocalPtr
.Overload
->Overload
& OVLD_FILE
)) {
882 DecodeOptions (RxBufPtr
, RxBufPtr
->u
.Dhcpv4
.file
, sizeof RxBufPtr
->u
.Dhcpv4
.file
);
883 } else if (!RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] && RxBufPtr
->u
.Dhcpv4
.file
[0]) {
884 RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] = (DHCPV4_OP_STRUCT
*) (RxBufPtr
->u
.Dhcpv4
.file
- sizeof (DHCPV4_OP_HEADER
));
886 RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]->Header
.Length
= (UINT8
) AsciiStrLen ((CHAR8
*) RxBufPtr
->u
.Dhcpv4
.file
);
889 LocalPtr
.OpPtr
= RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_CLASS_IDENTIFIER_IX
- 1];
891 if ((LocalPtr
.OpPtr
) &&
892 LocalPtr
.PxeClassStr
->Header
.Length
>= 9 &&
893 !CompareMem (LocalPtr
.PxeClassStr
->Class
, "PXEClient", 9)
895 RxBufPtr
->OpAdds
.Status
|= PXE_TYPE
;
899 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
903 PXE_BASECODE_DEVICE
*Private
,
908 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
910 RxBufPtr
= &((DHCP_RECEIVE_BUFFER
*) Private
->DhcpPacketBuffer
)[PacketIndex
];
914 &RxBuf
[RxBufIndex
].u
.Dhcpv4
,
915 sizeof (RxBuf
[RxBufIndex
].u
.Dhcpv4
)
918 Parse (RxBufPtr
, sizeof RxBufPtr
->u
.ReceiveBuffer
);
921 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
925 PXE_BASECODE_DEVICE
*Private
,
929 Private
->EfiBc
.Mode
->ProxyOfferReceived
= TRUE
;
930 CopyParseRxBuf (Private
, RxBufIndex
, PXE_OFFER_INDEX
);
933 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
937 PXE_BASECODE_DEVICE
*Private
,
938 EFI_PXE_BASE_CODE_PACKET
*PacketPtr
,
939 EFI_PXE_BASE_CODE_PACKET
*NewPacketPtr
,
943 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
945 DhcpRxBuf
= &((DHCP_RECEIVE_BUFFER
*) Private
->DhcpPacketBuffer
)[Index
];
948 (EFI_PXE_BASE_CODE_PACKET
*) &DhcpRxBuf
->u
.Dhcpv4
,
950 sizeof (*NewPacketPtr
)
953 CopyMem (&*PacketPtr
, &*NewPacketPtr
, sizeof (*NewPacketPtr
));
955 Parse (DhcpRxBuf
, sizeof DhcpRxBuf
->u
.ReceiveBuffer
);
958 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
961 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
966 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
970 // if a DHCP type, must be DHCPOFFER and must have server id
975 (LocalPtr
.MessageType
->Type
== DHCPACK
) &&
976 DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]
980 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
983 // if a discover type packet, make sure all required fields are present
987 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
990 PXE_OP_SERVER_LIST
*BootServerOpPtr
;
993 if ((DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) == 0) {
997 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
999 if (LocalPtr
.OpPtr
== NULL
) {
1000 LocalPtr
.OpPtr
= (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
1001 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
1004 // make sure all required fields are here
1005 // if mucticast enabled, need multicast address
1007 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
) &&
1008 (!DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1] || !IS_MULTICAST (((DHCPV4_OP_STRUCT
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1])->Data
))
1012 // missing required field
1016 // if a list, it better be good
1018 BootServerOpPtr
= (PXE_OP_SERVER_LIST
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1];
1020 if (BootServerOpPtr
!= NULL
) {
1021 PXE_SERVER_LIST
*BootServerListPtr
;
1023 INTN ServerEntryLen
;
1025 BootServerListPtr
= BootServerOpPtr
->ServerList
;
1026 ServerListLen
= BootServerOpPtr
->Header
.Length
;
1029 EFI_IPv4_ADDRESS
*IpListPtr
;
1032 IpCnt
= BootServerListPtr
->u
.Ipv4List
.IpCount
;
1034 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (IpCnt
- 1) * sizeof (EFI_IPv4_ADDRESS
);
1036 if (ServerListLen
< ServerEntryLen
) {
1038 // missing required field
1043 IpListPtr
= BootServerListPtr
->u
.Ipv4List
.IpList
;
1046 if (IS_MULTICAST (IpListPtr
)) {
1048 // missing required field
1056 BootServerListPtr
= (PXE_SERVER_LIST
*) IpListPtr
;
1057 } while (ServerListLen
-= ServerEntryLen
);
1060 // else there must be a list if use list enabled or multicast and
1061 // broadcast disabled
1063 else if ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) ||
1064 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
1067 // missing required field
1072 // if not USE_BOOTFILE or no bootfile given, must have menu stuff
1074 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& USE_BOOTFILE
) ||
1075 !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1079 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_MENU_IX
- 1];
1081 if (LocalPtr
.OpPtr
== NULL
|| !DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_PROMPT_IX
- 1]) {
1083 // missing required field
1088 // make sure menu valid
1090 MenuLth
= LocalPtr
.BootMenu
->Header
.Length
;
1091 LocalPtr
.BootMenuItem
= LocalPtr
.BootMenu
->MenuItem
;
1096 MenuItemLen
= LocalPtr
.BootMenuItem
->DataLen
;
1098 if (MenuItemLen
== 0) {
1100 // missing required field
1105 MenuItemLen
+= sizeof (*LocalPtr
.BootMenuItem
) - sizeof (LocalPtr
.BootMenuItem
->Data
);
1107 MenuLth
-= MenuItemLen
;
1108 LocalPtr
.BytePtr
+= MenuItemLen
;
1109 } while (MenuLth
> 0);
1113 // missing required field
1119 if (!DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
1120 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultBootItem
;
1126 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1129 DHCP_RECEIVE_BUFFER
*RxBufPtr
1132 return (BOOLEAN
) (DHCPOfferAckEdit (RxBufPtr
) ? AckEdit (RxBufPtr
) : FALSE
);
1135 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1142 PXE_BASECODE_DEVICE
*Private
,
1143 BOOLEAN (*ExtraEdit
)(DHCP_RECEIVE_BUFFER
*DhcpRxBuf
),
1144 UINT16 OpFlags
, // for Udp read
1145 EFI_IP_ADDRESS
*ServerIpPtr
,
1146 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
1147 EFI_IP_ADDRESS
*ClientIpPtr
,
1148 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
,
1149 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
,
1150 EFI_EVENT TimeoutEvent
1153 Routine description:
1154 Wait for an OFFER/ACK packet.
1157 Private := Pointer to PxeBc interface
1158 ExtraEdit := Pointer to extra option checking function
1159 OpFlags := UdpRead() option flags
1170 EFI_IP_ADDRESS ServerIp
;
1171 EFI_STATUS StatCode
;
1176 // Wait until we get a UDP packet.
1178 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1179 RxBufLen
= sizeof RxBuf
[0].u
.ReceiveBuffer
;
1181 if ((StatCode
= UdpRead (
1190 (UINTN
*) &RxBufLen
,
1191 &DhcpRxBuf
->u
.Dhcpv4
,
1193 )) != EFI_SUCCESS
) {
1194 if (StatCode
== EFI_TIMEOUT
) {
1195 StatCode
= EFI_NO_RESPONSE
;
1201 // got a packet - see if a good offer
1203 if (DhcpRxBuf
->u
.Dhcpv4
.op
!= BOOTP_REPLY
) {
1207 if (DhcpRxBuf
->u
.Dhcpv4
.xid
!= DHCPV4_TRANSMIT_BUFFER
.xid
) {
1211 if (*(UINT32
*) DHCPV4_TRANSMIT_BUFFER
.options
!= * (UINT32
*) DhcpRxBuf
->u
.Dhcpv4
.options
) {
1215 if (*(UINT8
*) &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
> 223) {
1220 DhcpRxBuf
->u
.Dhcpv4
.chaddr
,
1221 DHCPV4_TRANSMIT_BUFFER
.chaddr
,
1222 sizeof DhcpRxBuf
->u
.Dhcpv4
.chaddr
1230 Parse (DhcpRxBuf
, RxBufLen
);
1232 if (!(*ExtraEdit
) (DhcpRxBuf
)) {
1236 // Good DHCP packet.
1238 StatCode
= EFI_SUCCESS
;
1245 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1252 PXE_BASECODE_DEVICE
*Private
1255 EFI_IP_ADDRESS ClientIp
;
1256 EFI_IP_ADDRESS ServerIp
;
1257 EFI_STATUS StatCode
;
1258 EFI_EVENT TimeoutEvent
;
1265 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1268 for (Index
= 0; Index
< (sizeof Private
->ServerCount
) / sizeof Private
->ServerCount
[0]; ++Index
) {
1269 Private
->ServerCount
[Index
] = 0;
1270 Private
->GotProxy
[Index
] = 0;
1273 Private
->GotBootp
= 0;
1275 // these we throw away
1277 Private
->GotProxy
[DHCP_ONLY_IX
] = 1;
1278 StatCode
= gBS
->CreateEvent (
1286 if (EFI_ERROR (StatCode
)) {
1290 StatCode
= gBS
->SetTimer (
1293 Private
->Timeout
* 10000000 + 1000000
1296 if (EFI_ERROR (StatCode
)) {
1297 gBS
->CloseEvent (TimeoutEvent
);
1304 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1307 DhcpRxBuf
= &RxBuf
[NumOffers
];
1310 StatCode
= GetOfferAck (
1313 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
|
1314 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
|
1315 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1328 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
1331 // check type of offer
1333 if (LocalPtr
.OpPtr
== NULL
) {
1335 // bootp - we only need one and make sure has bootfile
1337 if (Private
->GotBootp
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1341 Private
->GotBootp
= (UINT8
) (NumOffers
+ 1);
1344 // if a DHCP type, must be DHCPOFFER and must have server id
1346 else if (LocalPtr
.MessageType
->Type
!= DHCPOFFER
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]) {
1352 // get type - PXE10, WfM11a, or BINL
1354 if (DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) {
1356 } else if (DhcpRxBuf
->OpAdds
.Status
& WfM11a_TYPE
) {
1358 // WfM - make sure it has a bootfile
1360 if (!DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1366 TypeIx
= (DhcpRxBuf
->OpAdds
.Status
& PXE_TYPE
) ? BINL_IX
: DHCP_ONLY_IX
;
1369 // check DHCP or proxy
1371 if (DhcpRxBuf
->u
.Dhcpv4
.yiaddr
== 0) {
1373 // proxy - only need one of each type if not BINL
1374 // and must have at least PXE_TYPE
1376 if (TypeIx
== BINL_IX
) {
1377 Private
->BinlProxies
[Private
->GotProxy
[BINL_IX
]++] = (UINT8
) NumOffers
;
1378 } else if (Private
->GotProxy
[TypeIx
]) {
1381 Private
->GotProxy
[TypeIx
] = (UINT8
) (NumOffers
+ 1);
1384 Private
->OfferCount
[TypeIx
][Private
->ServerCount
[TypeIx
]++] = (UINT8
) NumOffers
;
1388 if (++NumOffers
== MAX_OFFERS
) {
1393 gBS
->CloseEvent (TimeoutEvent
);
1394 Private
->NumOffersReceived
= NumOffers
;
1396 return (Private
->NumOffersReceived
) ? EFI_SUCCESS
: EFI_NO_RESPONSE
;
1399 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1407 PXE_BASECODE_DEVICE
*Private
1410 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1413 PxebcMode
= Private
->EfiBc
.Mode
;
1414 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1416 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1417 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1419 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opdeclinestr
),
1420 sizeof (DHCPOpStart
) - sizeof (struct opdeclinestr
),
1423 DHCPDECLINEoptions
.DhcpMessageType
.Type
= DHCPDECLINE
;
1424 CopyMem (&DHCPDECLINEoptions
.OpDeclineEnd
, &DHCP_REQ_OPTIONS
, sizeof (struct requestopendstr
));
1427 EFI_IP_ADDRESS TmpIp
;
1429 CopyMem (&TmpIp
, &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1435 &PxebcMode
->StationIp
,
1440 InitDhcpv4TxBuf (Private
);
1441 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1442 Private
->GoodStationIp
= FALSE
;
1445 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1453 PXE_BASECODE_DEVICE
*Private
1456 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1459 PxebcMode
= Private
->EfiBc
.Mode
;
1460 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1461 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1464 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opreleasestr
),
1465 sizeof (DHCPOpStart
) - sizeof (struct opreleasestr
),
1469 DHCPRELEASEoptions
.DhcpMessageType
.Type
= DHCPRELEASE
;
1472 &DHCPRELEASEoptions
.DhcServerIpPtr
,
1473 (DHCPV4_OP_SERVER_IP
*) DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1],
1474 sizeof DHCPRELEASEoptions
.DhcServerIpPtr
1477 DHCPRELEASEoptions
.End
[0] = OP_END
;
1480 EFI_IP_ADDRESS TmpIp
;
1482 CopyMem (&TmpIp
, &DHCPRELEASEoptions
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1488 &PxebcMode
->StationIp
,
1493 InitDhcpv4TxBuf (Private
);
1495 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1496 Private
->GoodStationIp
= FALSE
;
1500 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1504 PXE_BASECODE_DEVICE
*Private
,
1505 EFI_IP_ADDRESS
*ServerIpPtr
1508 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1509 EFI_STATUS StatCode
;
1510 EFI_EVENT TimeoutEvent
;
1515 StatCode
= gBS
->CreateEvent (
1523 if (EFI_ERROR (StatCode
)) {
1527 StatCode
= gBS
->SetTimer (
1530 Private
->Timeout
* 10000000 + 1000000
1533 if (EFI_ERROR (StatCode
)) {
1534 gBS
->CloseEvent (TimeoutEvent
);
1540 DhcpRxBuf
= &PXE_BINL_BUFFER
;
1543 EFI_PXE_BASE_CODE_UDP_PORT BINLSrvPort
;
1550 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1553 &Private
->EfiBc
.Mode
->StationIp
,
1554 &PSEUDO_DHCP_CLIENT_PORT
,
1561 // make sure from whom we wanted
1563 if (!DhcpRxBuf
->u
.Dhcpv4
.yiaddr
&& !CompareMem (
1565 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1566 sizeof (ServerIpPtr
->v4
)
1568 gBS
->CloseEvent (TimeoutEvent
);
1570 // got an ACK from server
1576 gBS
->CloseEvent (TimeoutEvent
);
1580 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1583 // make sure we can get BINL
1584 // send DHCPREQUEST to PXE server
1589 PXE_BASECODE_DEVICE
*Private
,
1593 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1594 EFI_IP_ADDRESS ServerIp
;
1598 DhcpRxBuf
= &RxBuf
[OfferIx
];
1601 // use next server address first.
1603 ServerIp
.Addr
[0] = DhcpRxBuf
->u
.Dhcpv4
.siaddr
;
1604 if (ServerIp
.Addr
[0] == 0) {
1606 // next server address is NULL, use option 54.
1609 ((EFI_IPv4_ADDRESS
*) &ServerIp
),
1610 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1611 sizeof (EFI_IPv4_ADDRESS
)
1616 // client IP address - filled in by client if it knows it
1619 ((EFI_IPv4_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
),
1620 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1621 sizeof (EFI_IPv4_ADDRESS
)
1624 SetMem (&DHCP_REQ_OPTIONS
, sizeof DHCP_REQ_OPTIONS
, OP_PAD
);
1625 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1626 DHCPV4_OPTIONS_BUFFER
.End
[0] = OP_END
;
1627 AddRouters (Private
, DhcpRxBuf
);
1628 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1630 for (Index
= 0; Index
< 3; Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Index
) {
1631 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
1634 // unicast DHCPREQUEST to PXE server
1639 &PseudoDhcpServerPort
,
1640 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1641 &PSEUDO_DHCP_CLIENT_PORT
1646 if (!GetBINLAck (Private
, &ServerIp
)) {
1650 // early exit failures
1651 // make sure a good ACK
1653 if (!DHCPOfferAckEdit (&PXE_BINL_BUFFER
) || (
1654 !(PXE_BINL_BUFFER
.OpAdds
.Status
& DISCOVER_TYPE
) && !PXE_BINL_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1660 Private
->EfiBc
.Mode
->ProxyOfferReceived
= TRUE
;
1664 // failed - reset seconds field, etc.
1666 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1670 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1674 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1678 PXE_BASECODE_DEVICE
*Private
,
1682 if (TryBINL (Private
, OfferIx
)) {
1686 return Release (Private
);
1689 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1692 TryFinishProxyBINL (
1693 PXE_BASECODE_DEVICE
*Private
1698 for (Index
= 0; Index
< Private
->GotProxy
[BINL_IX
]; ++Index
) {
1699 if (TryBINL (Private
, Private
->BinlProxies
[Index
])) {
1704 return Release (Private
);
1707 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1710 // try to finish DORA - send DHCP request, wait for ACK, check with ARP
1715 PXE_BASECODE_DEVICE
*Private
,
1719 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1720 EFI_IP_ADDRESS ClientIp
;
1721 EFI_IP_ADDRESS ServerIp
;
1722 EFI_STATUS StatCode
;
1724 EFI_EVENT TimeoutEvent
;
1727 // send DHCP request
1728 // if fail return false
1730 DhcpRxBuf
= &DHCPV4_ACK_BUFFER
;
1731 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
1732 CopyMem (&DHCP_REQ_OPTIONS
, &RequestOpEndStr
, sizeof (RequestOpEndStr
));
1733 // DHCP_REQ_OPTIONS = RequestOpEndStr;
1734 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[OfferIx
].u
.Dhcpv4
.yiaddr
;
1737 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1738 &((DHCPV4_OP_SERVER_IP
*) RxBuf
[OfferIx
].OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1739 sizeof DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
1743 Private
->EfiBc
.Mode
->SubnetMask
.Addr
,
1749 // broadcast DHCPREQUEST
1755 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1763 StatCode
= gBS
->CreateEvent (
1771 if (EFI_ERROR (StatCode
)) {
1775 StatCode
= gBS
->SetTimer (
1778 Private
->Timeout
* 10000000 + 1000000
1781 if (EFI_ERROR (StatCode
)) {
1782 gBS
->CloseEvent (TimeoutEvent
);
1792 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
,
1803 // check type of response - need DHCPACK
1806 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1807 &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
,
1808 sizeof (EFI_IPv4_ADDRESS
)
1810 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1811 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1812 sizeof (EFI_IPv4_ADDRESS
)
1818 // check with ARP that IP unused - good return true
1820 if (!SetStationIP (Private
)) {
1822 // fail - send DHCPDECLINE and return false
1824 DeclineOffer (Private
);
1828 LocalPtr
.OpPtr
= DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1830 if (LocalPtr
.OpPtr
!= NULL
) {
1832 (EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
,
1833 &LocalPtr
.SubnetMaskStr
->Ip
,
1834 sizeof (EFI_IPv4_ADDRESS
)
1838 AddRouters (Private
, DhcpRxBuf
);
1839 gBS
->CloseEvent (TimeoutEvent
);
1843 gBS
->CloseEvent (TimeoutEvent
);
1847 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1850 // try a DHCP server of appropriate type
1855 PXE_BASECODE_DEVICE
*Private
,
1862 // go through the DHCP servers of the requested type
1864 for (Index
= 0; Index
< Private
->ServerCount
[TypeIx
]; ++Index
) {
1865 if (TryFinishDORA (Private
, Index
= Private
->OfferCount
[TypeIx
][Index
])) {
1866 if (TypeIx
== BINL_IX
&& !TryFinishBINL (Private
, Index
)) {
1877 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1880 // try a DHCP only server and a proxy of appropriate type
1884 TryProxyFinishDORA (
1885 PXE_BASECODE_DEVICE
*Private
,
1891 if (!Private
->GotProxy
[TypeIx
]) {
1893 // no proxies of the type wanted
1898 // go through the DHCP only servers
1900 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1901 if (TryFinishDORA (Private
, Private
->OfferCount
[DHCP_ONLY_IX
][Index
])) {
1902 if (TypeIx
!= BINL_IX
) {
1903 CopyProxyRxBuf (Private
, Private
->GotProxy
[TypeIx
] - 1);
1904 } else if (!TryFinishProxyBINL (Private
)) {
1906 // if didn't work with this DHCP, won't work with any
1918 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1921 // getting to the bottom of the barrel
1925 TryAnyWithBootfileFinishDORA (
1926 PXE_BASECODE_DEVICE
*Private
1930 // try a DHCP only server who has a bootfile
1935 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1938 offer
= Private
->OfferCount
[DHCP_ONLY_IX
][Index
];
1940 if (RxBuf
[offer
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] && TryFinishDORA (Private
, offer
)) {
1945 // really at bottom - see if be have any bootps
1947 if (!Private
->GotBootp
) {
1951 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[Private
->GotBootp
- 1].u
.Dhcpv4
.yiaddr
;
1953 if (!SetStationIP (Private
)) {
1957 // treat BOOTP response as DHCP ACK packet
1959 CopyParseRxBuf (Private
, Private
->GotBootp
- 1, DHCPV4_ACK_INDEX
);
1961 LocalPtr
.OpPtr
= RxBuf
[Private
->GotBootp
- 1].OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1963 if (LocalPtr
.OpPtr
!= NULL
) {
1964 *(EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
= LocalPtr
.SubnetMaskStr
->Ip
;
1970 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1977 PXE_BASECODE_DEVICE
*Private
,
1981 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
1982 EFI_STATUS StatCode
;
1985 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
| EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
;
1988 Filter
.reserved
= 0;
1991 // set filter unicast or broadcast
1993 if ((StatCode
= IpFilter (Private
, &Filter
)) != EFI_SUCCESS
) {
1997 // seed random number with hardware address
1999 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2001 for (Private
->Timeout
= 1;
2002 Private
->Timeout
< 17;
2003 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), Private
->Timeout
<<= 1
2007 InitDhcpv4TxBuf (Private
);
2008 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2009 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2012 // broadcast DHCPDISCOVER
2014 StatCode
= DoUdpWrite (
2018 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2022 if (StatCode
!= EFI_SUCCESS
) {
2027 &Private
->EfiBc
.Mode
->DhcpDiscover
,
2028 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2029 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2035 if ((StatCode
= GetOffers (Private
)) != EFI_SUCCESS
) {
2036 if (StatCode
!= EFI_NO_RESPONSE
) {
2043 // select offer and reply DHCPREQUEST
2046 if (TryDHCPFinishDORA(Private
, PXE10_IX
) || // try DHCP with PXE10
2047 TryDHCPFinishDORA(Private
, WfM11a_IX
) || // no - try with WfM
2048 TryProxyFinishDORA(Private
, PXE10_IX
) || // no - try DHCP only and proxy with PXE10
2049 TryProxyFinishDORA(Private
, WfM11a_IX
) || // no - try DHCP only and proxy with WfM
2050 TryDHCPFinishDORA(Private
, BINL_IX
) || // no - try with WfM
2051 TryProxyFinishDORA(Private
, BINL_IX
) || // no - try DHCP only and proxy with PXE10
2052 TryAnyWithBootfileFinishDORA(Private
))
2062 NumOffers
= Private
->NumOffersReceived
;
2064 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2068 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
) {
2072 // check if a bootp server
2074 if (!RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1]) {
2076 // it is - just check ARP
2078 if (!SetStationIP (Private
)) {
2083 // else check if a DHCP only server
2085 else if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
))) {
2087 // it is a normal DHCP offer (without any PXE options), just finish the D.O.R.A by sending DHCP request.
2089 if (!TryFinishDORA (Private
, Index
)) {
2092 } else if (TryFinishDORA (Private
, Index
)) {
2093 if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) && !TryFinishBINL (Private
, Index
)) {
2098 DEBUG ((DEBUG_WARN
, "\nDoDhcpDora() Got packets. "));
2102 // now look for DHCP onlys and a Proxy
2104 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2108 // ignore proxies, bootps, non DHCP onlys, and bootable DHCPS
2110 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
||
2111 !RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1] ||
2112 RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
) ||
2113 RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
2118 // found non bootable DHCP only - try to find a proxy
2120 for (Index2
= 0; Index2
< NumOffers
; ++Index2
) {
2121 if (!RxBuf
[Index2
].u
.Dhcpv4
.yiaddr
) {
2122 if (!TryFinishDORA (Private
, Index
)) {
2129 if (RxBuf
[Index2
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) {
2130 CopyProxyRxBuf (Private
, Index2
);
2131 } else if (!TryFinishBINL (Private
, Index2
)) {
2135 DEBUG ((DEBUG_WARN
, "\nDoDhcpDora() Got packets. "));
2142 return EFI_NO_RESPONSE
;
2145 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2148 // determine if the server ip is in the ip list
2152 EFI_IP_ADDRESS
*ServerIpPtr
,
2153 PXE_SERVER_LISTS
*ServerListPtr
2158 if (!ServerListPtr
|| !ServerListPtr
->Ipv4List
.IpCount
) {
2162 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2165 &ServerListPtr
->Ipv4List
.IpList
[Index
],
2166 sizeof (EFI_IPv4_ADDRESS
)
2175 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2177 ExtractBootServerList (
2179 DHCPV4_OP_STRUCT
*ptr
,
2180 PXE_SERVER_LISTS
**ServerListPtr
2186 LocalPtr
.OpPtr
= ptr
;
2187 ServerListLen
= LocalPtr
.BootServersStr
->Header
.Length
;
2192 LocalPtr
.BootServerList
= LocalPtr
.BootServersStr
->ServerList
;
2194 while (ServerListLen
) {
2195 INTN ServerEntryLen
;
2197 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (LocalPtr
.BootServerList
->u
.Ipv4List
.IpCount
- 1) *
2198 sizeof (EFI_IPv4_ADDRESS
);
2200 if (NTOHS (LocalPtr
.BootServerList
->Type
) == Type
) {
2201 *ServerListPtr
= &LocalPtr
.BootServerList
->u
;
2205 (LocalPtr
.BytePtr
) += ServerEntryLen
;
2206 ServerListLen
-= ServerEntryLen
;
2212 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2215 PXE_BASECODE_DEVICE
*Private
2218 if (Private
->TransmitBuffer
!= NULL
) {
2219 gBS
->FreePool (Private
->TransmitBuffer
);
2220 Private
->TransmitBuffer
= NULL
;
2223 if (Private
->ReceiveBuffers
!= NULL
) {
2224 gBS
->FreePool (Private
->ReceiveBuffers
);
2225 Private
->ReceiveBuffers
= NULL
;
2229 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2232 PXE_BASECODE_DEVICE
*Private
2237 if (Private
->DhcpPacketBuffer
== NULL
) {
2238 Status
= gBS
->AllocatePool (
2239 EfiBootServicesData
,
2240 sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1),
2241 &Private
->DhcpPacketBuffer
2244 if (EFI_ERROR (Status
) || Private
->DhcpPacketBuffer
== NULL
) {
2245 Private
->DhcpPacketBuffer
= NULL
;
2251 Status
= gBS
->AllocatePool (
2252 EfiBootServicesData
,
2253 sizeof (EFI_PXE_BASE_CODE_PACKET
),
2254 &Private
->TransmitBuffer
2257 if (EFI_ERROR (Status
) || Private
->TransmitBuffer
== NULL
) {
2258 gBS
->FreePool (Private
->DhcpPacketBuffer
);
2259 Private
->DhcpPacketBuffer
= NULL
;
2260 Private
->TransmitBuffer
= NULL
;
2265 Status
= gBS
->AllocatePool (
2266 EfiBootServicesData
,
2267 sizeof (DHCP_RECEIVE_BUFFER
) * (MAX_OFFERS
),
2268 &Private
->ReceiveBuffers
2271 if (EFI_ERROR (Status
) || Private
->ReceiveBuffers
== NULL
) {
2272 gBS
->FreePool (Private
->TransmitBuffer
);
2273 gBS
->FreePool (Private
->DhcpPacketBuffer
);
2274 Private
->DhcpPacketBuffer
= NULL
;
2275 Private
->TransmitBuffer
= NULL
;
2276 Private
->ReceiveBuffers
= NULL
;
2284 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2293 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2294 IN BOOLEAN SortOffers
2297 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
2298 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2299 PXE_BASECODE_DEVICE
*Private
;
2300 EFI_STATUS StatCode
;
2303 // Lock the instance data and make sure started
2305 StatCode
= EFI_SUCCESS
;
2308 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
2309 return EFI_INVALID_PARAMETER
;
2312 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2314 if (Private
== NULL
) {
2315 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
2316 return EFI_INVALID_PARAMETER
;
2319 EfiAcquireLock (&Private
->Lock
);
2321 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2322 DEBUG ((DEBUG_ERROR
, "BC was not started."));
2323 EfiReleaseLock (&Private
->Lock
);
2324 return EFI_NOT_STARTED
;
2327 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
;
2329 Filter
.reserved
= 0;
2331 DEBUG ((DEBUG_INFO
, "\nBcDhcp() Enter. "));
2333 PxebcMode
= Private
->EfiBc
.Mode
;
2335 if (!GetMem (Private
)) {
2336 DEBUG ((DEBUG_ERROR
, "\nBcDhcp() GetMem() failed.\n"));
2337 EfiReleaseLock (&Private
->Lock
);
2338 return EFI_OUT_OF_RESOURCES
;
2341 PxebcMode
->DhcpDiscoverValid
= FALSE
;
2342 PxebcMode
->DhcpAckReceived
= FALSE
;
2343 PxebcMode
->ProxyOfferReceived
= FALSE
;
2345 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
2350 if (Private
->TotalSeconds
== 0) {
2352 // put in seconds field of DHCP send packets
2354 Private
->TotalSeconds
= 4;
2357 if ((StatCode
= DoDhcpDora (Private
, SortOffers
)) == EFI_SUCCESS
) {
2359 // success - copy packets
2361 PxebcMode
->DhcpDiscoverValid
= PxebcMode
->DhcpAckReceived
= TRUE
;
2364 &PxebcMode
->DhcpAck
,
2365 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_ACK_PACKET
,
2366 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2369 if (PxebcMode
->ProxyOfferReceived
) {
2371 &PxebcMode
->ProxyOffer
,
2372 (EFI_PXE_BASE_CODE_PACKET
*) &PXE_OFFER_PACKET
,
2373 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2378 // set filter back to unicast
2380 IpFilter (Private
, &Filter
);
2385 // Unlock the instance data
2387 DEBUG ((DEBUG_WARN
, "\nBcDhcp() Exit = %xh ", StatCode
));
2389 EfiReleaseLock (&Private
->Lock
);
2393 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2396 VerifyCredentialOption (
2404 // Fail verification if either pointer is NULL.
2406 if (tx
== NULL
|| rx
== NULL
) {
2410 // Fail verification if tx[0] is not a credential type option
2411 // or if the length is zero or not a multiple of four.
2413 if (tx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| tx
[1] == 0 || tx
[1] % 4 != 0) {
2417 // Fail verification if rx[0] is not a credential type option
2418 // or if the length is not equal to four.
2420 if (rx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| rx
[1] != 4) {
2424 // Look through transmitted credential types for a copy
2425 // of the received credential type.
2427 for (n
= 0; n
< tx
[1]; n
+= 4) {
2428 if (!CompareMem (&tx
[n
+ 2], &rx
[2], 4)) {
2436 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2444 PXE_BASECODE_DEVICE
*Private
,
2447 IN UINT16
*LayerPtr
,
2449 EFI_IP_ADDRESS
*DestPtr
,
2450 PXE_SERVER_LISTS
*ServerListPtr
2453 EFI_PXE_BASE_CODE_UDP_PORT ClientPort
;
2454 EFI_PXE_BASE_CODE_UDP_PORT ServerPort
;
2455 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2456 EFI_STATUS StatCode
;
2457 EFI_EVENT TimeoutEvent
;
2460 PxebcMode
= Private
->EfiBc
.Mode
;
2462 if (DestPtr
->Addr
[0] == 0) {
2463 DEBUG ((DEBUG_WARN
, "\nDoDiscover() !DestPtr->Addr[0]"));
2464 return EFI_INVALID_PARAMETER
;
2467 // seed random number with hardware address
2469 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2471 if (DestPtr
->Addr
[0] == BroadcastIP
.Addr
[0]) {
2472 ClientPort
= DHCPClientPort
;
2473 ServerPort
= DhcpServerPort
;
2475 ClientPort
= PSEUDO_DHCP_CLIENT_PORT
;
2476 ServerPort
= PseudoDhcpServerPort
;
2480 *LayerPtr
|= PXE_BOOT_LAYER_CREDENTIAL_FLAG
;
2482 *LayerPtr
&= PXE_BOOT_LAYER_MASK
;
2485 for (Private
->Timeout
= 1;
2486 Private
->Timeout
< 5;
2487 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Private
->Timeout
2489 InitDhcpv4TxBuf (Private
);
2491 // initialize DHCP message structure
2493 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2494 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2496 &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2497 &PxebcMode
->StationIp
,
2498 sizeof DHCPV4_TRANSMIT_BUFFER
.ciaddr
2501 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
2502 DISCOVERoptions
.Header
.OpCode
= OP_VENDOR_SPECIFIC
;
2503 DISCOVERoptions
.BootItem
.Header
.OpCode
= VEND_PXE_BOOT_ITEM
;
2504 DISCOVERoptions
.BootItem
.Header
.Length
= DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM
);
2505 DISCOVERoptions
.BootItem
.Type
= HTONS (Type
);
2506 DISCOVERoptions
.BootItem
.Layer
= HTONS (*LayerPtr
);
2509 EFI_BIS_PROTOCOL
*BisPtr
;
2510 BIS_APPLICATION_HANDLE BisAppHandle
;
2511 EFI_BIS_DATA
*BisDataSigInfo
;
2512 EFI_BIS_SIGNATURE_INFO
*BisSigInfo
;
2516 BisPtr
= PxebcBisStart (
2522 if (BisPtr
== NULL
) {
2524 // %%TBD - In order to get here, BIS must have
2525 // been present when PXEBC.Start() was called.
2526 // BIS had to be shutdown/removed/damaged
2527 // before PXEBC.Discover() was called.
2528 // Do we need to document a specific error
2531 return EFI_OUT_OF_RESOURCES
;
2534 // Compute number of credential types.
2536 Index2
= BisDataSigInfo
->Length
/ sizeof (EFI_BIS_SIGNATURE_INFO
);
2538 DISCREDoptions
.Header
.OpCode
= VEND_PXE_CREDENTIAL_TYPES
;
2540 DISCREDoptions
.Header
.Length
= (UINT8
) (Index2
* sizeof (PXE_CREDENTIAL
));
2542 OpLen
= (UINT8
) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
) + sizeof (DHCPV4_OP_HEADER
) + DISCREDoptions
.Header
.Length
);
2544 BisSigInfo
= (EFI_BIS_SIGNATURE_INFO
*) BisDataSigInfo
->Data
;
2546 for (Index
= 0; Index
< Index2
; ++Index
) {
2549 CopyMem (&x
, &BisSigInfo
[Index
], sizeof x
);
2551 CopyMem (&DISCREDoptions
.Credentials
[Index
], &x
, sizeof x
);
2554 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
2556 OpLen
= DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
);
2559 DISCOVERoptions
.Header
.Length
= OpLen
;
2561 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
- 1] = OP_END
;
2562 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
] = OP_END
;
2564 StatCode
= DoUdpWrite (
2568 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2572 if (StatCode
!= EFI_SUCCESS
) {
2578 StatCode
= gBS
->CreateEvent (
2586 if (EFI_ERROR (StatCode
)) {
2590 StatCode
= gBS
->SetTimer (
2593 Private
->Timeout
* 10000000 + 1000000
2596 if (EFI_ERROR (StatCode
)) {
2597 gBS
->CloseEvent (TimeoutEvent
);
2604 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
2608 RxBufPtr
= UseBis
? &PXE_BIS_BUFFER
: &PXE_ACK_BUFFER
;
2609 ZeroMem (&Private
->ServerIp
, sizeof (EFI_IP_ADDRESS
));
2615 (EFI_IP_ADDRESS
*) &Private
->ServerIp
,
2617 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2625 // check type of response - need PXEClient DHCPACK of proper type with bootfile
2627 if (!(RxBufPtr
->OpAdds
.Status
& PXE_TYPE
) ||
2628 (UseBis
&& (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
)) ||
2629 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] ||
2630 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1] ||
2631 !InServerList((EFI_IP_ADDRESS
*)&((DHCPV4_OP_SERVER_IP
*)RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
-1])->Ip
, ServerListPtr
)) {
2636 TmpType
= TmpLayer
= 0;
2638 if (RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
2639 TmpType
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Type
);
2641 if (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
) {
2642 TmpLayer
= (UINT16
) (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
>> 8);
2644 TmpLayer
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
);
2648 if (TmpType
!= Type
) {
2653 if (!RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]) {
2657 if (!VerifyCredentialOption (
2658 (UINT8
*) &DISCREDoptions
.Header
,
2659 (UINT8
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]
2665 *LayerPtr
= TmpLayer
;
2669 &PxebcMode
->PxeBisReply
,
2670 &RxBufPtr
->u
.Dhcpv4
,
2671 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2674 PxebcMode
->PxeBisReplyReceived
= TRUE
;
2676 StatCode
= DoDiscover (
2678 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2686 gBS
->CloseEvent (TimeoutEvent
);
2690 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= TRUE
;
2693 &PxebcMode
->PxeDiscover
,
2694 &*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2695 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
)
2699 &PxebcMode
->PxeReply
,
2700 &*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
,
2701 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
)
2704 AddRouters (Private
, RxBufPtr
);
2706 gBS
->CloseEvent (TimeoutEvent
);
2710 gBS
->CloseEvent (TimeoutEvent
);
2718 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2722 Private := Pointer to PxeBc interface
2727 McastServerListPtr :=
2735 PXE_BASECODE_DEVICE
*Private
,
2737 IN UINT16
*LayerPtr
,
2739 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*DiscoverInfoPtr
,
2740 PXE_SERVER_LISTS
*McastServerListPtr
,
2741 PXE_SERVER_LISTS
*ServerListPtr
2744 EFI_IP_ADDRESS DestIp
;
2745 EFI_STATUS StatCode
;
2747 DEBUG ((DEBUG_INFO
, "\nDiscover() Type=%d Layer=%d ", Type
, *LayerPtr
));
2750 DEBUG ((DEBUG_INFO
, "BIS "));
2753 // get dest IP addr - mcast, bcast, or unicast
2755 if (DiscoverInfoPtr
->UseMCast
) {
2756 DestIp
.v4
= DiscoverInfoPtr
->ServerMCastIp
.v4
;
2760 "\nDiscover() MCast %d.%d.%d.%d ",
2767 if ((StatCode
= DoDiscover (
2769 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2775 )) != EFI_TIMEOUT
) {
2778 "\nDiscover() status == %r (%Xh)",
2787 if (DiscoverInfoPtr
->UseBCast
) {
2788 DEBUG ((DEBUG_INFO
, "\nDiscver() BCast "));
2790 if ((StatCode
= DoDiscover (
2792 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2798 )) != EFI_TIMEOUT
) {
2800 DEBUG ((DEBUG_WARN
, "\nDiscover() status == %r (%Xh)", StatCode
, StatCode
));
2806 if (DiscoverInfoPtr
->UseUCast
) {
2811 "\nDiscover() UCast IP#=%d ",
2812 ServerListPtr
->Ipv4List
.IpCount
)
2815 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2816 CopyMem (&DestIp
, &ServerListPtr
->Ipv4List
.IpList
[Index
], 4);
2820 "\nDiscover() UCast %d.%d.%d.%d ",
2827 if ((StatCode
= DoDiscover (
2829 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2835 )) != EFI_TIMEOUT
) {
2838 "\nDiscover() status == %r (%Xh)",
2848 DEBUG ((DEBUG_WARN
, "\nDiscover() TIMEOUT"));
2853 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2865 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
2867 IN UINT16
*LayerPtr
,
2869 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
* DiscoverInfoPtr OPTIONAL
2872 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
2873 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2874 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
2875 PXE_SERVER_LISTS DefaultSrvList
;
2876 PXE_SERVER_LISTS
*ServerListPtr
;
2877 PXE_SERVER_LISTS
*McastServerListPtr
;
2881 BOOLEAN AcquiredSrvList
;
2882 EFI_STATUS StatCode
;
2883 PXE_BASECODE_DEVICE
*Private
;
2886 // Lock the instance data and make sure started
2888 StatCode
= EFI_SUCCESS
;
2891 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
2892 return EFI_INVALID_PARAMETER
;
2895 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2897 if (Private
== NULL
) {
2898 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2899 return EFI_INVALID_PARAMETER
;
2902 EfiAcquireLock (&Private
->Lock
);
2904 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2905 DEBUG ((DEBUG_ERROR
, "BC was not started."));
2906 EfiReleaseLock (&Private
->Lock
);
2907 return EFI_NOT_STARTED
;
2910 ServerListPtr
= NULL
;
2911 McastServerListPtr
= NULL
;
2912 AcquiredSrvList
= FALSE
;
2914 PxebcMode
= Private
->EfiBc
.Mode
;
2916 if (!GetMem (Private
)) {
2917 EfiReleaseLock (&Private
->Lock
);
2918 return EFI_OUT_OF_RESOURCES
;
2922 if (!PxebcMode
->BisSupported
) {
2923 EfiReleaseLock (&Private
->Lock
);
2924 return EFI_INVALID_PARAMETER
;
2928 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
2930 if (Private
->TotalSeconds
== 0) {
2932 // put in seconds field of DHCP send packets
2934 Private
->TotalSeconds
= 4;
2937 ZeroMem (&DefaultInfo
, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO
));
2940 // if layer number not zero, use previous discover
2942 if (*LayerPtr
!= 0) {
2943 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0"));
2945 if (DiscoverInfoPtr
!= NULL
) {
2946 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n"));
2948 EfiReleaseLock (&Private
->Lock
);
2949 return EFI_INVALID_PARAMETER
;
2952 if (!PxebcMode
->PxeDiscoverValid
) {
2953 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n"));
2955 EfiReleaseLock (&Private
->Lock
);
2956 return EFI_INVALID_PARAMETER
;
2959 if (!PxebcMode
->PxeReplyReceived
) {
2960 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n"));
2962 EfiReleaseLock (&Private
->Lock
);
2963 return EFI_INVALID_PARAMETER
;
2966 if (UseBis
&& !PxebcMode
->PxeBisReplyReceived
) {
2967 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n"));
2969 EfiReleaseLock (&Private
->Lock
);
2970 return EFI_INVALID_PARAMETER
;
2973 DefaultInfo
.UseUCast
= TRUE
;
2974 DiscoverInfoPtr
= &DefaultInfo
;
2976 DefaultSrvList
.Ipv4List
.IpCount
= 1;
2977 CopyMem (&DefaultSrvList
.Ipv4List
.IpList
[0], &Private
->ServerIp
, 4);
2979 ServerListPtr
= &DefaultSrvList
;
2982 // layer is zero - see if info is supplied or if we need to use info from a cached offer
2984 else if (!DiscoverInfoPtr
) {
2986 // not supplied - generate it
2987 // make sure that there is cached, appropriate information
2988 // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail
2990 DhcpRxBuf
= (PxebcMode
->ProxyOfferReceived
) ? &PXE_OFFER_BUFFER
: &DHCPV4_ACK_BUFFER
;
2992 if (!PxebcMode
->DhcpAckReceived
|| !(DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
)) {
2993 DEBUG ((DEBUG_WARN
, "\nBcDiscover() !ack && !proxy"));
2994 EfiReleaseLock (&Private
->Lock
);
2995 return EFI_INVALID_PARAMETER
;
2998 DiscoverInfoPtr
= &DefaultInfo
;
3000 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
3003 // if multicast enabled, need multicast address
3005 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
)) {
3006 DefaultInfo
.UseMCast
= TRUE
;
3009 ((EFI_IPv4_ADDRESS
*) &DefaultInfo
.ServerMCastIp
),
3010 &((DHCPV4_OP_IP_ADDRESS
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1])->Ip
,
3011 sizeof (EFI_IPv4_ADDRESS
)
3015 DefaultInfo
.UseBCast
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_BCAST
) == 0);
3017 DefaultInfo
.MustUseList
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) != 0);
3019 DefaultInfo
.UseUCast
= (BOOLEAN
)
3021 (DefaultInfo
.MustUseList
) ||
3022 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
3025 if ((DefaultInfo
.UseUCast
| DefaultInfo
.MustUseList
) && !ExtractBootServerList (
3027 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1],
3030 DEBUG ((DEBUG_WARN
, "\nBcDiscover() type not in list"));
3031 EfiReleaseLock (&Private
->Lock
);
3032 return EFI_INVALID_PARAMETER
;
3036 // Info supplied - make SrvList if required
3037 // if we use ucast discovery or must use list, there better be one
3039 else if (DiscoverInfoPtr
->UseUCast
|| DiscoverInfoPtr
->MustUseList
) {
3041 // there better be a list
3043 if (DiscoverInfoPtr
->IpCnt
== 0) {
3044 DEBUG ((DEBUG_WARN
, "\nBcDiscover() no bootserver list"));
3045 EfiReleaseLock (&Private
->Lock
);
3046 return EFI_INVALID_PARAMETER
;
3051 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3052 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3053 if (DiscoverInfoPtr
->SrvList
[Index
].AcceptAnyResponse
) {
3055 DEBUG ((DEBUG_WARN
, "\nBcDiscover() accept any?"));
3056 EfiReleaseLock (&Private
->Lock
);
3057 return EFI_INVALID_PARAMETER
;
3060 DefaultSrvList
.Ipv4List
.IpCount
= 0;
3061 ServerListPtr
= &DefaultSrvList
;
3071 DEBUG ((DEBUG_WARN
, "\nBcDiscover() !Index2?"));
3072 EfiReleaseLock (&Private
->Lock
);
3073 return EFI_INVALID_PARAMETER
;
3076 if (ServerListPtr
== NULL
) {
3077 ServerListPtr
= AllocatePool (
3078 sizeof (PXEV4_SERVER_LIST
) + (Index2
- 1) * sizeof (EFI_IPv4_ADDRESS
)
3081 if (ServerListPtr
== NULL
) {
3082 EfiReleaseLock (&Private
->Lock
);
3083 return EFI_OUT_OF_RESOURCES
;
3086 // build an array of IP addresses from the server list
3088 AcquiredSrvList
= TRUE
;
3089 ServerListPtr
->Ipv4List
.IpCount
= (UINT8
) Index2
;
3091 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3092 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3094 &ServerListPtr
->Ipv4List
.IpList
[Index2
++],
3095 &DiscoverInfoPtr
->SrvList
[Index
].IpAddr
.v4
,
3096 sizeof ServerListPtr
->Ipv4List
.IpList
[0]
3103 if (DiscoverInfoPtr
->MustUseList
) {
3104 McastServerListPtr
= ServerListPtr
;
3107 if (!(DiscoverInfoPtr
->UseMCast
|| DiscoverInfoPtr
->UseBCast
|| DiscoverInfoPtr
->UseUCast
)) {
3108 DEBUG ((DEBUG_WARN
, "\nBcDiscover() Nothing to use!\n"));
3110 EfiReleaseLock (&Private
->Lock
);
3111 return EFI_INVALID_PARAMETER
;
3114 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= PxebcMode
->PxeBisReplyReceived
= FALSE
;
3116 StatCode
= Discover (
3126 if (AcquiredSrvList
) {
3127 gBS
->FreePool (ServerListPtr
);
3133 // Unlock the instance data
3137 "\nBcDiscover() status == %r (%Xh)\n",
3142 EfiReleaseLock (&Private
->Lock
);
3146 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3155 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
3156 BOOLEAN
*NewDhcpDiscoverValid
, OPTIONAL
3157 BOOLEAN
*NewDhcpAckReceived
, OPTIONAL
3158 BOOLEAN
*NewProxyOfferReceived
, OPTIONAL
3159 BOOLEAN
*NewPxeDiscoverValid
, OPTIONAL
3160 BOOLEAN
*NewPxeReplyReceived
, OPTIONAL
3161 BOOLEAN
*NewPxeBisReplyReceived
, OPTIONAL
3162 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
3163 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
3164 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
3165 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
3166 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
3167 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
3170 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
3172 PXE_BASECODE_DEVICE
*Private
;
3175 // Lock the instance data and make sure started
3179 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
3180 return EFI_INVALID_PARAMETER
;
3183 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
3185 if (Private
== NULL
) {
3186 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
3187 return EFI_INVALID_PARAMETER
;
3190 EfiAcquireLock (&Private
->Lock
);
3192 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
3193 DEBUG ((DEBUG_ERROR
, "BC was not started."));
3194 EfiReleaseLock (&Private
->Lock
);
3195 return EFI_NOT_STARTED
;
3198 PxebcMode
= Private
->EfiBc
.Mode
;
3200 if (Private
->DhcpPacketBuffer
== NULL
) {
3201 Status
= gBS
->AllocatePool (
3202 EfiBootServicesData
,
3203 sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1),
3204 &Private
->DhcpPacketBuffer
3207 if (EFI_ERROR (Status
) || Private
->DhcpPacketBuffer
== NULL
) {
3208 Private
->DhcpPacketBuffer
= NULL
;
3209 EfiReleaseLock (&Private
->Lock
);
3210 return EFI_OUT_OF_RESOURCES
;
3219 Private
->FileSize
= 0;
3220 if (NewDhcpDiscoverValid
!= NULL
) {
3221 PxebcMode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
3224 if (NewDhcpAckReceived
!= NULL
) {
3225 PxebcMode
->DhcpAckReceived
= *NewDhcpAckReceived
;
3228 if (NewProxyOfferReceived
!= NULL
) {
3229 PxebcMode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
3232 if (NewPxeDiscoverValid
!= NULL
) {
3233 PxebcMode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
3236 if (NewPxeReplyReceived
!= NULL
) {
3237 PxebcMode
->PxeReplyReceived
= *NewPxeReplyReceived
;
3240 if (NewPxeBisReplyReceived
!= NULL
) {
3241 PxebcMode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
3244 if (NewDhcpDiscover
!= NULL
) {
3246 &PxebcMode
->DhcpDiscover
,
3248 sizeof *NewDhcpDiscover
3252 if (NewDhcpAck
!= NULL
) {
3253 CopyParse (Private
, &PxebcMode
->DhcpAck
, NewDhcpAck
, DHCPV4_ACK_INDEX
);
3256 if (NewProxyOffer
!= NULL
) {
3257 CopyParse (Private
, &PxebcMode
->ProxyOffer
, NewProxyOffer
, PXE_OFFER_INDEX
);
3260 if (NewPxeDiscover
!= NULL
) {
3262 &PxebcMode
->PxeDiscover
,
3264 sizeof *NewPxeDiscover
3268 if (NewPxeReply
!= NULL
) {
3269 CopyParse (Private
, &PxebcMode
->PxeReply
, NewPxeReply
, PXE_ACK_INDEX
);
3272 if (NewPxeBisReply
!= NULL
) {
3273 CopyParse (Private
, &PxebcMode
->PxeBisReply
, NewPxeBisReply
, PXE_BIS_INDEX
);
3276 // Unlock the instance data
3278 EfiReleaseLock (&Private
->Lock
);
3282 /* eof - pxe_bc_dhcp.c */