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 (DHCPDECLINEoptions
.OpDeclineEnd
));
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 (DHCP_REQ_OPTIONS
));
1733 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[OfferIx
].u
.Dhcpv4
.yiaddr
;
1736 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1737 &((DHCPV4_OP_SERVER_IP
*) RxBuf
[OfferIx
].OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1738 sizeof DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
1742 Private
->EfiBc
.Mode
->SubnetMask
.Addr
,
1748 // broadcast DHCPREQUEST
1754 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1762 StatCode
= gBS
->CreateEvent (
1770 if (EFI_ERROR (StatCode
)) {
1774 StatCode
= gBS
->SetTimer (
1777 Private
->Timeout
* 10000000 + 1000000
1780 if (EFI_ERROR (StatCode
)) {
1781 gBS
->CloseEvent (TimeoutEvent
);
1791 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
,
1802 // check type of response - need DHCPACK
1805 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1806 &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
,
1807 sizeof (EFI_IPv4_ADDRESS
)
1809 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1810 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1811 sizeof (EFI_IPv4_ADDRESS
)
1817 // check with ARP that IP unused - good return true
1819 if (!SetStationIP (Private
)) {
1821 // fail - send DHCPDECLINE and return false
1823 DeclineOffer (Private
);
1827 LocalPtr
.OpPtr
= DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1829 if (LocalPtr
.OpPtr
!= NULL
) {
1831 (EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
,
1832 &LocalPtr
.SubnetMaskStr
->Ip
,
1833 sizeof (EFI_IPv4_ADDRESS
)
1837 AddRouters (Private
, DhcpRxBuf
);
1838 gBS
->CloseEvent (TimeoutEvent
);
1842 gBS
->CloseEvent (TimeoutEvent
);
1846 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1849 // try a DHCP server of appropriate type
1854 PXE_BASECODE_DEVICE
*Private
,
1861 // go through the DHCP servers of the requested type
1863 for (Index
= 0; Index
< Private
->ServerCount
[TypeIx
]; ++Index
) {
1864 if (TryFinishDORA (Private
, Index
= Private
->OfferCount
[TypeIx
][Index
])) {
1865 if (TypeIx
== BINL_IX
&& !TryFinishBINL (Private
, Index
)) {
1876 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1879 // try a DHCP only server and a proxy of appropriate type
1883 TryProxyFinishDORA (
1884 PXE_BASECODE_DEVICE
*Private
,
1890 if (!Private
->GotProxy
[TypeIx
]) {
1892 // no proxies of the type wanted
1897 // go through the DHCP only servers
1899 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1900 if (TryFinishDORA (Private
, Private
->OfferCount
[DHCP_ONLY_IX
][Index
])) {
1901 if (TypeIx
!= BINL_IX
) {
1902 CopyProxyRxBuf (Private
, Private
->GotProxy
[TypeIx
] - 1);
1903 } else if (!TryFinishProxyBINL (Private
)) {
1905 // if didn't work with this DHCP, won't work with any
1917 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1920 // getting to the bottom of the barrel
1924 TryAnyWithBootfileFinishDORA (
1925 PXE_BASECODE_DEVICE
*Private
1929 // try a DHCP only server who has a bootfile
1934 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1937 offer
= Private
->OfferCount
[DHCP_ONLY_IX
][Index
];
1939 if (RxBuf
[offer
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] && TryFinishDORA (Private
, offer
)) {
1944 // really at bottom - see if be have any bootps
1946 if (!Private
->GotBootp
) {
1950 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[Private
->GotBootp
- 1].u
.Dhcpv4
.yiaddr
;
1952 if (!SetStationIP (Private
)) {
1956 // treat BOOTP response as DHCP ACK packet
1958 CopyParseRxBuf (Private
, Private
->GotBootp
- 1, DHCPV4_ACK_INDEX
);
1960 LocalPtr
.OpPtr
= RxBuf
[Private
->GotBootp
- 1].OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1962 if (LocalPtr
.OpPtr
!= NULL
) {
1963 *(EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
= LocalPtr
.SubnetMaskStr
->Ip
;
1969 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1976 PXE_BASECODE_DEVICE
*Private
,
1980 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
1981 EFI_STATUS StatCode
;
1984 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
| EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
;
1987 Filter
.reserved
= 0;
1990 // set filter unicast or broadcast
1992 if ((StatCode
= IpFilter (Private
, &Filter
)) != EFI_SUCCESS
) {
1996 // seed random number with hardware address
1998 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2000 for (Private
->Timeout
= 1;
2001 Private
->Timeout
< 17;
2002 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), Private
->Timeout
<<= 1
2006 InitDhcpv4TxBuf (Private
);
2007 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2008 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2011 // broadcast DHCPDISCOVER
2013 StatCode
= DoUdpWrite (
2017 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2021 if (StatCode
!= EFI_SUCCESS
) {
2026 &Private
->EfiBc
.Mode
->DhcpDiscover
,
2027 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2028 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2034 if ((StatCode
= GetOffers (Private
)) != EFI_SUCCESS
) {
2035 if (StatCode
!= EFI_NO_RESPONSE
) {
2042 // select offer and reply DHCPREQUEST
2045 if (TryDHCPFinishDORA(Private
, PXE10_IX
) || // try DHCP with PXE10
2046 TryDHCPFinishDORA(Private
, WfM11a_IX
) || // no - try with WfM
2047 TryProxyFinishDORA(Private
, PXE10_IX
) || // no - try DHCP only and proxy with PXE10
2048 TryProxyFinishDORA(Private
, WfM11a_IX
) || // no - try DHCP only and proxy with WfM
2049 TryDHCPFinishDORA(Private
, BINL_IX
) || // no - try with WfM
2050 TryProxyFinishDORA(Private
, BINL_IX
) || // no - try DHCP only and proxy with PXE10
2051 TryAnyWithBootfileFinishDORA(Private
))
2061 NumOffers
= Private
->NumOffersReceived
;
2063 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2067 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
) {
2071 // check if a bootp server
2073 if (!RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1]) {
2075 // it is - just check ARP
2077 if (!SetStationIP (Private
)) {
2082 // else check if a DHCP only server
2084 else if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
))) {
2086 // it is a normal DHCP offer (without any PXE options), just finish the D.O.R.A by sending DHCP request.
2088 if (!TryFinishDORA (Private
, Index
)) {
2091 } else if (TryFinishDORA (Private
, Index
)) {
2092 if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) && !TryFinishBINL (Private
, Index
)) {
2097 DEBUG ((DEBUG_WARN
, "\nDoDhcpDora() Got packets. "));
2101 // now look for DHCP onlys and a Proxy
2103 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2107 // ignore proxies, bootps, non DHCP onlys, and bootable DHCPS
2109 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
||
2110 !RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1] ||
2111 RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
) ||
2112 RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
2117 // found non bootable DHCP only - try to find a proxy
2119 for (Index2
= 0; Index2
< NumOffers
; ++Index2
) {
2120 if (!RxBuf
[Index2
].u
.Dhcpv4
.yiaddr
) {
2121 if (!TryFinishDORA (Private
, Index
)) {
2128 if (RxBuf
[Index2
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) {
2129 CopyProxyRxBuf (Private
, Index2
);
2130 } else if (!TryFinishBINL (Private
, Index2
)) {
2134 DEBUG ((DEBUG_WARN
, "\nDoDhcpDora() Got packets. "));
2141 return EFI_NO_RESPONSE
;
2144 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2147 // determine if the server ip is in the ip list
2151 EFI_IP_ADDRESS
*ServerIpPtr
,
2152 PXE_SERVER_LISTS
*ServerListPtr
2157 if (!ServerListPtr
|| !ServerListPtr
->Ipv4List
.IpCount
) {
2161 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2164 &ServerListPtr
->Ipv4List
.IpList
[Index
],
2165 sizeof (EFI_IPv4_ADDRESS
)
2174 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2176 ExtractBootServerList (
2178 DHCPV4_OP_STRUCT
*ptr
,
2179 PXE_SERVER_LISTS
**ServerListPtr
2185 LocalPtr
.OpPtr
= ptr
;
2186 ServerListLen
= LocalPtr
.BootServersStr
->Header
.Length
;
2191 LocalPtr
.BootServerList
= LocalPtr
.BootServersStr
->ServerList
;
2193 while (ServerListLen
) {
2194 INTN ServerEntryLen
;
2196 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (LocalPtr
.BootServerList
->u
.Ipv4List
.IpCount
- 1) *
2197 sizeof (EFI_IPv4_ADDRESS
);
2199 if (NTOHS (LocalPtr
.BootServerList
->Type
) == Type
) {
2200 *ServerListPtr
= &LocalPtr
.BootServerList
->u
;
2204 (LocalPtr
.BytePtr
) += ServerEntryLen
;
2205 ServerListLen
-= ServerEntryLen
;
2211 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2214 PXE_BASECODE_DEVICE
*Private
2217 if (Private
->TransmitBuffer
!= NULL
) {
2218 gBS
->FreePool (Private
->TransmitBuffer
);
2219 Private
->TransmitBuffer
= NULL
;
2222 if (Private
->ReceiveBuffers
!= NULL
) {
2223 gBS
->FreePool (Private
->ReceiveBuffers
);
2224 Private
->ReceiveBuffers
= NULL
;
2228 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2231 PXE_BASECODE_DEVICE
*Private
2236 if (Private
->DhcpPacketBuffer
== NULL
) {
2237 Status
= gBS
->AllocatePool (
2238 EfiBootServicesData
,
2239 sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1),
2240 &Private
->DhcpPacketBuffer
2243 if (EFI_ERROR (Status
) || Private
->DhcpPacketBuffer
== NULL
) {
2244 Private
->DhcpPacketBuffer
= NULL
;
2250 Status
= gBS
->AllocatePool (
2251 EfiBootServicesData
,
2252 sizeof (EFI_PXE_BASE_CODE_PACKET
),
2253 &Private
->TransmitBuffer
2256 if (EFI_ERROR (Status
) || Private
->TransmitBuffer
== NULL
) {
2257 gBS
->FreePool (Private
->DhcpPacketBuffer
);
2258 Private
->DhcpPacketBuffer
= NULL
;
2259 Private
->TransmitBuffer
= NULL
;
2264 Status
= gBS
->AllocatePool (
2265 EfiBootServicesData
,
2266 sizeof (DHCP_RECEIVE_BUFFER
) * (MAX_OFFERS
),
2267 &Private
->ReceiveBuffers
2270 if (EFI_ERROR (Status
) || Private
->ReceiveBuffers
== NULL
) {
2271 gBS
->FreePool (Private
->TransmitBuffer
);
2272 gBS
->FreePool (Private
->DhcpPacketBuffer
);
2273 Private
->DhcpPacketBuffer
= NULL
;
2274 Private
->TransmitBuffer
= NULL
;
2275 Private
->ReceiveBuffers
= NULL
;
2283 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2292 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2293 IN BOOLEAN SortOffers
2296 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
2297 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2298 PXE_BASECODE_DEVICE
*Private
;
2299 EFI_STATUS StatCode
;
2302 // Lock the instance data and make sure started
2304 StatCode
= EFI_SUCCESS
;
2307 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
2308 return EFI_INVALID_PARAMETER
;
2311 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2313 if (Private
== NULL
) {
2314 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
2315 return EFI_INVALID_PARAMETER
;
2318 EfiAcquireLock (&Private
->Lock
);
2320 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2321 DEBUG ((DEBUG_ERROR
, "BC was not started."));
2322 EfiReleaseLock (&Private
->Lock
);
2323 return EFI_NOT_STARTED
;
2326 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
;
2328 Filter
.reserved
= 0;
2330 DEBUG ((DEBUG_INFO
, "\nBcDhcp() Enter. "));
2332 PxebcMode
= Private
->EfiBc
.Mode
;
2334 if (!GetMem (Private
)) {
2335 DEBUG ((DEBUG_ERROR
, "\nBcDhcp() GetMem() failed.\n"));
2336 EfiReleaseLock (&Private
->Lock
);
2337 return EFI_OUT_OF_RESOURCES
;
2340 PxebcMode
->DhcpDiscoverValid
= FALSE
;
2341 PxebcMode
->DhcpAckReceived
= FALSE
;
2342 PxebcMode
->ProxyOfferReceived
= FALSE
;
2344 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
2349 if (Private
->TotalSeconds
== 0) {
2351 // put in seconds field of DHCP send packets
2353 Private
->TotalSeconds
= 4;
2356 if ((StatCode
= DoDhcpDora (Private
, SortOffers
)) == EFI_SUCCESS
) {
2358 // success - copy packets
2360 PxebcMode
->DhcpDiscoverValid
= PxebcMode
->DhcpAckReceived
= TRUE
;
2363 &PxebcMode
->DhcpAck
,
2364 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_ACK_PACKET
,
2365 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2368 if (PxebcMode
->ProxyOfferReceived
) {
2370 &PxebcMode
->ProxyOffer
,
2371 (EFI_PXE_BASE_CODE_PACKET
*) &PXE_OFFER_PACKET
,
2372 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2377 // set filter back to unicast
2379 IpFilter (Private
, &Filter
);
2384 // Unlock the instance data
2386 DEBUG ((DEBUG_WARN
, "\nBcDhcp() Exit = %xh ", StatCode
));
2388 EfiReleaseLock (&Private
->Lock
);
2392 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2395 VerifyCredentialOption (
2403 // Fail verification if either pointer is NULL.
2405 if (tx
== NULL
|| rx
== NULL
) {
2409 // Fail verification if tx[0] is not a credential type option
2410 // or if the length is zero or not a multiple of four.
2412 if (tx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| tx
[1] == 0 || tx
[1] % 4 != 0) {
2416 // Fail verification if rx[0] is not a credential type option
2417 // or if the length is not equal to four.
2419 if (rx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| rx
[1] != 4) {
2423 // Look through transmitted credential types for a copy
2424 // of the received credential type.
2426 for (n
= 0; n
< tx
[1]; n
+= 4) {
2427 if (!CompareMem (&tx
[n
+ 2], &rx
[2], 4)) {
2435 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2443 PXE_BASECODE_DEVICE
*Private
,
2446 IN UINT16
*LayerPtr
,
2448 EFI_IP_ADDRESS
*DestPtr
,
2449 PXE_SERVER_LISTS
*ServerListPtr
2452 EFI_PXE_BASE_CODE_UDP_PORT ClientPort
;
2453 EFI_PXE_BASE_CODE_UDP_PORT ServerPort
;
2454 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2455 EFI_STATUS StatCode
;
2456 EFI_EVENT TimeoutEvent
;
2459 PxebcMode
= Private
->EfiBc
.Mode
;
2461 if (DestPtr
->Addr
[0] == 0) {
2462 DEBUG ((DEBUG_WARN
, "\nDoDiscover() !DestPtr->Addr[0]"));
2463 return EFI_INVALID_PARAMETER
;
2466 // seed random number with hardware address
2468 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2470 if (DestPtr
->Addr
[0] == BroadcastIP
.Addr
[0]) {
2471 ClientPort
= DHCPClientPort
;
2472 ServerPort
= DhcpServerPort
;
2474 ClientPort
= PSEUDO_DHCP_CLIENT_PORT
;
2475 ServerPort
= PseudoDhcpServerPort
;
2479 *LayerPtr
|= PXE_BOOT_LAYER_CREDENTIAL_FLAG
;
2481 *LayerPtr
&= PXE_BOOT_LAYER_MASK
;
2484 for (Private
->Timeout
= 1;
2485 Private
->Timeout
< 5;
2486 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Private
->Timeout
2488 InitDhcpv4TxBuf (Private
);
2490 // initialize DHCP message structure
2492 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2493 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2495 &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2496 &PxebcMode
->StationIp
,
2497 sizeof DHCPV4_TRANSMIT_BUFFER
.ciaddr
2500 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
2501 DISCOVERoptions
.Header
.OpCode
= OP_VENDOR_SPECIFIC
;
2502 DISCOVERoptions
.BootItem
.Header
.OpCode
= VEND_PXE_BOOT_ITEM
;
2503 DISCOVERoptions
.BootItem
.Header
.Length
= DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM
);
2504 DISCOVERoptions
.BootItem
.Type
= HTONS (Type
);
2505 DISCOVERoptions
.BootItem
.Layer
= HTONS (*LayerPtr
);
2508 EFI_BIS_PROTOCOL
*BisPtr
;
2509 BIS_APPLICATION_HANDLE BisAppHandle
;
2510 EFI_BIS_DATA
*BisDataSigInfo
;
2511 EFI_BIS_SIGNATURE_INFO
*BisSigInfo
;
2515 BisPtr
= PxebcBisStart (
2521 if (BisPtr
== NULL
) {
2523 // %%TBD - In order to get here, BIS must have
2524 // been present when PXEBC.Start() was called.
2525 // BIS had to be shutdown/removed/damaged
2526 // before PXEBC.Discover() was called.
2527 // Do we need to document a specific error
2530 return EFI_OUT_OF_RESOURCES
;
2533 // Compute number of credential types.
2535 Index2
= BisDataSigInfo
->Length
/ sizeof (EFI_BIS_SIGNATURE_INFO
);
2537 DISCREDoptions
.Header
.OpCode
= VEND_PXE_CREDENTIAL_TYPES
;
2539 DISCREDoptions
.Header
.Length
= (UINT8
) (Index2
* sizeof (PXE_CREDENTIAL
));
2541 OpLen
= (UINT8
) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
) + sizeof (DHCPV4_OP_HEADER
) + DISCREDoptions
.Header
.Length
);
2543 BisSigInfo
= (EFI_BIS_SIGNATURE_INFO
*) BisDataSigInfo
->Data
;
2545 for (Index
= 0; Index
< Index2
; ++Index
) {
2548 CopyMem (&x
, &BisSigInfo
[Index
], sizeof x
);
2550 CopyMem (&DISCREDoptions
.Credentials
[Index
], &x
, sizeof x
);
2553 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
2555 OpLen
= DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
);
2558 DISCOVERoptions
.Header
.Length
= OpLen
;
2560 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
- 1] = OP_END
;
2561 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
] = OP_END
;
2563 StatCode
= DoUdpWrite (
2567 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2571 if (StatCode
!= EFI_SUCCESS
) {
2577 StatCode
= gBS
->CreateEvent (
2585 if (EFI_ERROR (StatCode
)) {
2589 StatCode
= gBS
->SetTimer (
2592 Private
->Timeout
* 10000000 + 1000000
2595 if (EFI_ERROR (StatCode
)) {
2596 gBS
->CloseEvent (TimeoutEvent
);
2603 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
2607 RxBufPtr
= UseBis
? &PXE_BIS_BUFFER
: &PXE_ACK_BUFFER
;
2608 ZeroMem (&Private
->ServerIp
, sizeof (EFI_IP_ADDRESS
));
2614 (EFI_IP_ADDRESS
*) &Private
->ServerIp
,
2616 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2624 // check type of response - need PXEClient DHCPACK of proper type with bootfile
2626 if (!(RxBufPtr
->OpAdds
.Status
& PXE_TYPE
) ||
2627 (UseBis
&& (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
)) ||
2628 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] ||
2629 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1] ||
2630 !InServerList((EFI_IP_ADDRESS
*)&((DHCPV4_OP_SERVER_IP
*)RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
-1])->Ip
, ServerListPtr
)) {
2635 TmpType
= TmpLayer
= 0;
2637 if (RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
2638 TmpType
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Type
);
2640 if (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
) {
2641 TmpLayer
= (UINT16
) (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
>> 8);
2643 TmpLayer
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
);
2647 if (TmpType
!= Type
) {
2652 if (!RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]) {
2656 if (!VerifyCredentialOption (
2657 (UINT8
*) &DISCREDoptions
.Header
,
2658 (UINT8
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]
2664 *LayerPtr
= TmpLayer
;
2668 &PxebcMode
->PxeBisReply
,
2669 &RxBufPtr
->u
.Dhcpv4
,
2670 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2673 PxebcMode
->PxeBisReplyReceived
= TRUE
;
2675 StatCode
= DoDiscover (
2677 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2685 gBS
->CloseEvent (TimeoutEvent
);
2689 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= TRUE
;
2692 &PxebcMode
->PxeDiscover
,
2693 &*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2694 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
)
2698 &PxebcMode
->PxeReply
,
2699 &*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
,
2700 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
)
2703 AddRouters (Private
, RxBufPtr
);
2705 gBS
->CloseEvent (TimeoutEvent
);
2709 gBS
->CloseEvent (TimeoutEvent
);
2717 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2721 Private := Pointer to PxeBc interface
2726 McastServerListPtr :=
2734 PXE_BASECODE_DEVICE
*Private
,
2736 IN UINT16
*LayerPtr
,
2738 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*DiscoverInfoPtr
,
2739 PXE_SERVER_LISTS
*McastServerListPtr
,
2740 PXE_SERVER_LISTS
*ServerListPtr
2743 EFI_IP_ADDRESS DestIp
;
2744 EFI_STATUS StatCode
;
2746 DEBUG ((DEBUG_INFO
, "\nDiscover() Type=%d Layer=%d ", Type
, *LayerPtr
));
2749 DEBUG ((DEBUG_INFO
, "BIS "));
2752 // get dest IP addr - mcast, bcast, or unicast
2754 if (DiscoverInfoPtr
->UseMCast
) {
2755 DestIp
.v4
= DiscoverInfoPtr
->ServerMCastIp
.v4
;
2759 "\nDiscover() MCast %d.%d.%d.%d ",
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
) {
2777 "\nDiscover() status == %r (%Xh)",
2786 if (DiscoverInfoPtr
->UseBCast
) {
2787 DEBUG ((DEBUG_INFO
, "\nDiscver() BCast "));
2789 if ((StatCode
= DoDiscover (
2791 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2797 )) != EFI_TIMEOUT
) {
2799 DEBUG ((DEBUG_WARN
, "\nDiscover() status == %r (%Xh)", StatCode
, StatCode
));
2805 if (DiscoverInfoPtr
->UseUCast
) {
2810 "\nDiscover() UCast IP#=%d ",
2811 ServerListPtr
->Ipv4List
.IpCount
)
2814 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2815 CopyMem (&DestIp
, &ServerListPtr
->Ipv4List
.IpList
[Index
], 4);
2819 "\nDiscover() UCast %d.%d.%d.%d ",
2826 if ((StatCode
= DoDiscover (
2828 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2834 )) != EFI_TIMEOUT
) {
2837 "\nDiscover() status == %r (%Xh)",
2847 DEBUG ((DEBUG_WARN
, "\nDiscover() TIMEOUT"));
2852 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2864 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
2866 IN UINT16
*LayerPtr
,
2868 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
* DiscoverInfoPtr OPTIONAL
2871 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
2872 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2873 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
2874 PXE_SERVER_LISTS DefaultSrvList
;
2875 PXE_SERVER_LISTS
*ServerListPtr
;
2876 PXE_SERVER_LISTS
*McastServerListPtr
;
2880 BOOLEAN AcquiredSrvList
;
2881 EFI_STATUS StatCode
;
2882 PXE_BASECODE_DEVICE
*Private
;
2885 // Lock the instance data and make sure started
2887 StatCode
= EFI_SUCCESS
;
2890 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
2891 return EFI_INVALID_PARAMETER
;
2894 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2896 if (Private
== NULL
) {
2897 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2898 return EFI_INVALID_PARAMETER
;
2901 EfiAcquireLock (&Private
->Lock
);
2903 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2904 DEBUG ((DEBUG_ERROR
, "BC was not started."));
2905 EfiReleaseLock (&Private
->Lock
);
2906 return EFI_NOT_STARTED
;
2909 ServerListPtr
= NULL
;
2910 McastServerListPtr
= NULL
;
2911 AcquiredSrvList
= FALSE
;
2913 PxebcMode
= Private
->EfiBc
.Mode
;
2915 if (!GetMem (Private
)) {
2916 EfiReleaseLock (&Private
->Lock
);
2917 return EFI_OUT_OF_RESOURCES
;
2921 if (!PxebcMode
->BisSupported
) {
2922 EfiReleaseLock (&Private
->Lock
);
2923 return EFI_INVALID_PARAMETER
;
2927 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
2929 if (Private
->TotalSeconds
== 0) {
2931 // put in seconds field of DHCP send packets
2933 Private
->TotalSeconds
= 4;
2936 ZeroMem (&DefaultInfo
, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO
));
2939 // if layer number not zero, use previous discover
2941 if (*LayerPtr
!= 0) {
2942 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0"));
2944 if (DiscoverInfoPtr
!= NULL
) {
2945 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n"));
2947 EfiReleaseLock (&Private
->Lock
);
2948 return EFI_INVALID_PARAMETER
;
2951 if (!PxebcMode
->PxeDiscoverValid
) {
2952 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n"));
2954 EfiReleaseLock (&Private
->Lock
);
2955 return EFI_INVALID_PARAMETER
;
2958 if (!PxebcMode
->PxeReplyReceived
) {
2959 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n"));
2961 EfiReleaseLock (&Private
->Lock
);
2962 return EFI_INVALID_PARAMETER
;
2965 if (UseBis
&& !PxebcMode
->PxeBisReplyReceived
) {
2966 DEBUG ((DEBUG_WARN
, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n"));
2968 EfiReleaseLock (&Private
->Lock
);
2969 return EFI_INVALID_PARAMETER
;
2972 DefaultInfo
.UseUCast
= TRUE
;
2973 DiscoverInfoPtr
= &DefaultInfo
;
2975 DefaultSrvList
.Ipv4List
.IpCount
= 1;
2976 CopyMem (&DefaultSrvList
.Ipv4List
.IpList
[0], &Private
->ServerIp
, 4);
2978 ServerListPtr
= &DefaultSrvList
;
2981 // layer is zero - see if info is supplied or if we need to use info from a cached offer
2983 else if (!DiscoverInfoPtr
) {
2985 // not supplied - generate it
2986 // make sure that there is cached, appropriate information
2987 // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail
2989 DhcpRxBuf
= (PxebcMode
->ProxyOfferReceived
) ? &PXE_OFFER_BUFFER
: &DHCPV4_ACK_BUFFER
;
2991 if (!PxebcMode
->DhcpAckReceived
|| !(DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
)) {
2992 DEBUG ((DEBUG_WARN
, "\nBcDiscover() !ack && !proxy"));
2993 EfiReleaseLock (&Private
->Lock
);
2994 return EFI_INVALID_PARAMETER
;
2997 DiscoverInfoPtr
= &DefaultInfo
;
2999 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
3002 // if multicast enabled, need multicast address
3004 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
)) {
3005 DefaultInfo
.UseMCast
= TRUE
;
3008 ((EFI_IPv4_ADDRESS
*) &DefaultInfo
.ServerMCastIp
),
3009 &((DHCPV4_OP_IP_ADDRESS
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1])->Ip
,
3010 sizeof (EFI_IPv4_ADDRESS
)
3014 DefaultInfo
.UseBCast
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_BCAST
) == 0);
3016 DefaultInfo
.MustUseList
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) != 0);
3018 DefaultInfo
.UseUCast
= (BOOLEAN
)
3020 (DefaultInfo
.MustUseList
) ||
3021 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
3024 if ((DefaultInfo
.UseUCast
| DefaultInfo
.MustUseList
) && !ExtractBootServerList (
3026 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1],
3029 DEBUG ((DEBUG_WARN
, "\nBcDiscover() type not in list"));
3030 EfiReleaseLock (&Private
->Lock
);
3031 return EFI_INVALID_PARAMETER
;
3035 // Info supplied - make SrvList if required
3036 // if we use ucast discovery or must use list, there better be one
3038 else if (DiscoverInfoPtr
->UseUCast
|| DiscoverInfoPtr
->MustUseList
) {
3040 // there better be a list
3042 if (DiscoverInfoPtr
->IpCnt
== 0) {
3043 DEBUG ((DEBUG_WARN
, "\nBcDiscover() no bootserver list"));
3044 EfiReleaseLock (&Private
->Lock
);
3045 return EFI_INVALID_PARAMETER
;
3050 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3051 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3052 if (DiscoverInfoPtr
->SrvList
[Index
].AcceptAnyResponse
) {
3054 DEBUG ((DEBUG_WARN
, "\nBcDiscover() accept any?"));
3055 EfiReleaseLock (&Private
->Lock
);
3056 return EFI_INVALID_PARAMETER
;
3059 DefaultSrvList
.Ipv4List
.IpCount
= 0;
3060 ServerListPtr
= &DefaultSrvList
;
3070 DEBUG ((DEBUG_WARN
, "\nBcDiscover() !Index2?"));
3071 EfiReleaseLock (&Private
->Lock
);
3072 return EFI_INVALID_PARAMETER
;
3075 if (ServerListPtr
== NULL
) {
3076 ServerListPtr
= AllocatePool (
3077 sizeof (PXEV4_SERVER_LIST
) + (Index2
- 1) * sizeof (EFI_IPv4_ADDRESS
)
3080 if (ServerListPtr
== NULL
) {
3081 EfiReleaseLock (&Private
->Lock
);
3082 return EFI_OUT_OF_RESOURCES
;
3085 // build an array of IP addresses from the server list
3087 AcquiredSrvList
= TRUE
;
3088 ServerListPtr
->Ipv4List
.IpCount
= (UINT8
) Index2
;
3090 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3091 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3093 &ServerListPtr
->Ipv4List
.IpList
[Index2
++],
3094 &DiscoverInfoPtr
->SrvList
[Index
].IpAddr
.v4
,
3095 sizeof ServerListPtr
->Ipv4List
.IpList
[0]
3102 if (DiscoverInfoPtr
->MustUseList
) {
3103 McastServerListPtr
= ServerListPtr
;
3106 if (!(DiscoverInfoPtr
->UseMCast
|| DiscoverInfoPtr
->UseBCast
|| DiscoverInfoPtr
->UseUCast
)) {
3107 DEBUG ((DEBUG_WARN
, "\nBcDiscover() Nothing to use!\n"));
3109 EfiReleaseLock (&Private
->Lock
);
3110 return EFI_INVALID_PARAMETER
;
3113 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= PxebcMode
->PxeBisReplyReceived
= FALSE
;
3115 StatCode
= Discover (
3125 if (AcquiredSrvList
) {
3126 gBS
->FreePool (ServerListPtr
);
3132 // Unlock the instance data
3136 "\nBcDiscover() status == %r (%Xh)\n",
3141 EfiReleaseLock (&Private
->Lock
);
3145 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3154 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
3155 BOOLEAN
*NewDhcpDiscoverValid
, OPTIONAL
3156 BOOLEAN
*NewDhcpAckReceived
, OPTIONAL
3157 BOOLEAN
*NewProxyOfferReceived
, OPTIONAL
3158 BOOLEAN
*NewPxeDiscoverValid
, OPTIONAL
3159 BOOLEAN
*NewPxeReplyReceived
, OPTIONAL
3160 BOOLEAN
*NewPxeBisReplyReceived
, OPTIONAL
3161 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
3162 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
3163 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
3164 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
3165 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
3166 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
3169 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
3171 PXE_BASECODE_DEVICE
*Private
;
3174 // Lock the instance data and make sure started
3178 DEBUG ((DEBUG_ERROR
, "BC *This pointer == NULL"));
3179 return EFI_INVALID_PARAMETER
;
3182 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
3184 if (Private
== NULL
) {
3185 DEBUG ((DEBUG_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
3186 return EFI_INVALID_PARAMETER
;
3189 EfiAcquireLock (&Private
->Lock
);
3191 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
3192 DEBUG ((DEBUG_ERROR
, "BC was not started."));
3193 EfiReleaseLock (&Private
->Lock
);
3194 return EFI_NOT_STARTED
;
3197 PxebcMode
= Private
->EfiBc
.Mode
;
3199 if (Private
->DhcpPacketBuffer
== NULL
) {
3200 Status
= gBS
->AllocatePool (
3201 EfiBootServicesData
,
3202 sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1),
3203 &Private
->DhcpPacketBuffer
3206 if (EFI_ERROR (Status
) || Private
->DhcpPacketBuffer
== NULL
) {
3207 Private
->DhcpPacketBuffer
= NULL
;
3208 EfiReleaseLock (&Private
->Lock
);
3209 return EFI_OUT_OF_RESOURCES
;
3218 Private
->FileSize
= 0;
3219 if (NewDhcpDiscoverValid
!= NULL
) {
3220 PxebcMode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
3223 if (NewDhcpAckReceived
!= NULL
) {
3224 PxebcMode
->DhcpAckReceived
= *NewDhcpAckReceived
;
3227 if (NewProxyOfferReceived
!= NULL
) {
3228 PxebcMode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
3231 if (NewPxeDiscoverValid
!= NULL
) {
3232 PxebcMode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
3235 if (NewPxeReplyReceived
!= NULL
) {
3236 PxebcMode
->PxeReplyReceived
= *NewPxeReplyReceived
;
3239 if (NewPxeBisReplyReceived
!= NULL
) {
3240 PxebcMode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
3243 if (NewDhcpDiscover
!= NULL
) {
3245 &PxebcMode
->DhcpDiscover
,
3247 sizeof *NewDhcpDiscover
3251 if (NewDhcpAck
!= NULL
) {
3252 CopyParse (Private
, &PxebcMode
->DhcpAck
, NewDhcpAck
, DHCPV4_ACK_INDEX
);
3255 if (NewProxyOffer
!= NULL
) {
3256 CopyParse (Private
, &PxebcMode
->ProxyOffer
, NewProxyOffer
, PXE_OFFER_INDEX
);
3259 if (NewPxeDiscover
!= NULL
) {
3261 &PxebcMode
->PxeDiscover
,
3263 sizeof *NewPxeDiscover
3267 if (NewPxeReply
!= NULL
) {
3268 CopyParse (Private
, &PxebcMode
->PxeReply
, NewPxeReply
, PXE_ACK_INDEX
);
3271 if (NewPxeBisReply
!= NULL
) {
3272 CopyParse (Private
, &PxebcMode
->PxeBisReply
, NewPxeBisReply
, PXE_BIS_INDEX
);
3275 // Unlock the instance data
3277 EfiReleaseLock (&Private
->Lock
);
3281 /* eof - pxe_bc_dhcp.c */