3 Copyright (c) 2006 - 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.
23 STATIC EFI_PXE_BASE_CODE_UDP_PORT DhcpServerPort
= DHCP_SERVER_PORT
;
24 STATIC EFI_PXE_BASE_CODE_UDP_PORT DHCPClientPort
= DHCP_CLIENT_PORT
;
25 STATIC EFI_PXE_BASE_CODE_UDP_PORT PseudoDhcpServerPort
= PXE_DISCOVERY_PORT
;
26 #define PSEUDO_DHCP_CLIENT_PORT PseudoDhcpServerPort
27 STATIC EFI_IP_ADDRESS BroadcastIP
= { { 0xffffffff } };
28 STATIC EFI_IP_ADDRESS DefaultSubnetMask
= { { 0xffffff00 } };
31 DHCPV4_OP_STRUCT
*OpPtr
;
32 PXE_OP_SERVER_LIST
*BootServersStr
;
33 PXE_SERVER_LIST
*BootServerList
;
34 PXE_BOOT_MENU_ENTRY
*BootMenuItem
;
35 PXE_OP_DISCOVERY_CONTROL
*DiscoveryControl
;
36 PXE_OP_BOOT_MENU
*BootMenu
;
37 PXE_OP_BOOT_ITEM
*BootItem
;
38 DHCPV4_OP_VENDOR_OPTIONS
*VendorOptions
;
39 DHCPV4_OP_OVERLOAD
*Overload
;
40 DHCPV4_OP_CLASS
*PxeClassStr
;
41 DHCPV4_OP_SUBNET_MASK
*SubnetMaskStr
;
42 DHCPV4_OP_MESSAGE_TYPE
*MessageType
;
48 // option structure for DHCPREQUEST at end of DISCOVER options
49 // and for DHCPDECLINE
51 STATIC
const struct requestopendstr
{
52 DHCPV4_OP_REQUESTED_IP OpReqIP
;
53 DHCPV4_OP_SERVER_IP DhcServerIpPtr
;
60 DHCPV4_OPTION_LENGTH(DHCPV4_OP_REQUESTED_IP
)
66 DHCPV4_OPTION_LENGTH(DHCPV4_OP_SERVER_IP
)
74 #define DHCP_REQ_OPTIONS (*(struct requestopendstr *) DHCPV4_OPTIONS_BUFFER.End)
76 PXE_OP_BOOT_ITEM DefaultBootItem
= {
79 DHCPV4_OPTION_LENGTH(PXE_OP_BOOT_ITEM
)
85 // PXE discovery control default structure
87 STATIC PXE_OP_DISCOVERY_CONTROL DefaultDisCtl
= {
88 { VEND_PXE_DISCOVERY_CONTROL
, DHCPV4_OPTION_LENGTH(PXE_OP_DISCOVERY_CONTROL
) },
93 // PXE credentials option structure
100 DHCPV4_OP_HEADER Header
;
101 PXE_CREDENTIAL Credentials
[1];
102 } PXE_OP_CREDENTIAL_TYPES
;
105 // option structure for PXE discover (without credentials)
107 typedef struct { // discoveropendstr {
108 DHCPV4_OP_HEADER Header
; // vendor options
109 PXE_OP_BOOT_ITEM BootItem
;
110 UINT8 End
[1]; // if credentials option, it starts here
111 } PXE_DISCOVER_OPTIONS
;
113 #define DISCOVERoptions (*(PXE_DISCOVER_OPTIONS *) DHCPV4_OPTIONS_BUFFER.End)
114 #define DISCREDoptions (*(PXE_OP_CREDENTIAL_TYPES *) DISCOVERoptions.End)
117 // common option beginning for all our DHCP messages except
118 // DHCPDECLINE and DHCPRELEASE
120 STATIC
struct optionsstr
{
122 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType
;
123 DHCPV4_OP_MAX_MESSAGE_SIZE DhcpMaxMessageSize
;
124 DHCPV4_OP_REQUESTED_OPTIONS DhcpRequestedOptions
;
125 DHCPV4_OP_PLATFORM_ID DhcpPlatformId
;
126 DHCPV4_OP_NETWORK_INTERFACE DhcpNetworkInterface
;
127 DHCPV4_OP_ARCHITECTURE_TYPE DhcpClientArchitecture
;
128 DHCPV4_OP_CLASS_ID DhcpClassIdentifier
;
132 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
138 DHCPOpStart
.DhcpCookie
[0] = 99;
139 DHCPOpStart
.DhcpCookie
[1] = 130;
140 DHCPOpStart
.DhcpCookie
[2] = 83;
141 DHCPOpStart
.DhcpCookie
[3] = 99;
142 DHCPOpStart
.DhcpMessageType
.Header
.OpCode
= OP_DHCP_MESSAGE_TYPE
;
143 DHCPOpStart
.DhcpMessageType
.Header
.Length
= 1;
144 DHCPOpStart
.DhcpMessageType
.Type
= DHCPDISCOVER
;
145 DHCPOpStart
.DhcpMaxMessageSize
.Header
.OpCode
= OP_DHCP_MAX_MESSAGE_SZ
;
146 DHCPOpStart
.DhcpMaxMessageSize
.Header
.Length
= 2;
147 DHCPOpStart
.DhcpMaxMessageSize
.MaxSize
[0] = MAX_DHCP_MSG_SZ
>> 8;
148 DHCPOpStart
.DhcpMaxMessageSize
.MaxSize
[1] = MAX_DHCP_MSG_SZ
& 0xff;
149 DHCPOpStart
.DhcpRequestedOptions
.Header
.OpCode
= OP_DHCP_PARM_REQ_LIST
;
150 DHCPOpStart
.DhcpRequestedOptions
.Header
.Length
= sizeof (DHCPV4_REQUESTED_OPTIONS_DATA
);
151 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_SUBNET_MASK
= OP_SUBNET_MASK
; /* 1 */
152 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_TIME_OFFSET
= OP_TIME_OFFSET
; /* 2 */
153 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_ROUTER_LIST
= OP_ROUTER_LIST
; /* 3 */
154 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_TIME_SERVERS
= OP_TIME_SERVERS
; /* 4 */
155 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NAME_SERVERS
= OP_NAME_SERVERS
; /* 5 */
156 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DNS_SERVERS
= OP_DNS_SERVERS
; /* 6 */
157 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_HOST_NAME
= OP_HOST_NAME
; /* 12 */
158 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_BOOT_FILE_SZ
= OP_BOOT_FILE_SZ
; /* 13 */
159 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DOMAIN_NAME
= OP_DOMAIN_NAME
; /* 15 */
160 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_ROOT_PATH
= OP_ROOT_PATH
; /* 17 */
161 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_EXTENSION_PATH
= OP_EXTENSION_PATH
; /* 18 */
162 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_MAX_DATAGRAM_SZ
= OP_MAX_DATAGRAM_SZ
; /* 22 */
163 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DEFAULT_TTL
= OP_DEFAULT_TTL
; /* 23 */
164 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_BROADCAST_ADD
= OP_BROADCAST_ADD
; /* 28 */
165 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NIS_DOMAIN_NAME
= OP_NIS_DOMAIN_NAME
; /* 40 */
166 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NIS_SERVERS
= OP_NIS_SERVERS
; /* 41 */
167 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_NTP_SERVERS
= OP_NTP_SERVERS
; /* 42 */
168 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_VENDOR_SPECIFIC
= OP_VENDOR_SPECIFIC
; /* 43 */
169 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_REQ_IP_ADD
= OP_DHCP_REQ_IP_ADD
; /* 50 */
170 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_LEASE_TIME
= OP_DHCP_LEASE_TIME
; /* 51 */
171 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_SERVER_IP
= OP_DHCP_SERVER_IP
; /* 54 */
172 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_RENEWAL_TIME
= OP_DHCP_RENEWAL_TIME
; /* 58 */
173 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_REBINDING_TIME
= OP_DHCP_REBINDING_TIME
; /* 59 */
174 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_CLASS_IDENTIFIER
= OP_DHCP_CLASS_IDENTIFIER
; /* 60 */
175 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_TFTP_SERVER_NAME
= OP_DHCP_TFTP_SERVER_NAME
; /* 66 */
176 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_BOOTFILE
= OP_DHCP_BOOTFILE
; /* 67 */
177 DHCPOpStart
.DhcpRequestedOptions
.Data
._OP_DHCP_PLATFORM_ID
= OP_DHCP_PLATFORM_ID
; /* 97 */
178 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption128
= 128;
179 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption129
= 129;
180 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption130
= 130;
181 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption131
= 131;
182 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption132
= 132;
183 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption133
= 133, DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption134
= 134;
184 DHCPOpStart
.DhcpRequestedOptions
.Data
.VendorOption135
= 135;
185 DHCPOpStart
.DhcpPlatformId
.Header
.OpCode
= OP_DHCP_PLATFORM_ID
;
186 DHCPOpStart
.DhcpPlatformId
.Header
.Length
= DHCPV4_OPTION_LENGTH (DHCPV4_OP_PLATFORM_ID
);
187 DHCPOpStart
.DhcpNetworkInterface
.Header
.OpCode
= OP_DHCP_NETWORK_ARCH
;
188 DHCPOpStart
.DhcpNetworkInterface
.Header
.Length
= DHCPV4_OPTION_LENGTH (DHCPV4_OP_NETWORK_INTERFACE
);
189 DHCPOpStart
.DhcpNetworkInterface
.Type
= 0;
190 DHCPOpStart
.DhcpNetworkInterface
.MajorVersion
= 0;
191 DHCPOpStart
.DhcpNetworkInterface
.MinorVersion
= 0;
192 DHCPOpStart
.DhcpClientArchitecture
.Header
.OpCode
= OP_DHCP_SYSTEM_ARCH
;
193 DHCPOpStart
.DhcpClientArchitecture
.Header
.Length
= DHCPV4_OPTION_LENGTH (DHCPV4_OP_ARCHITECTURE_TYPE
);
194 DHCPOpStart
.DhcpClientArchitecture
.Type
= HTONS (SYS_ARCH
);
195 DHCPOpStart
.DhcpClassIdentifier
.Header
.OpCode
= OP_DHCP_CLASS_IDENTIFIER
;
196 DHCPOpStart
.DhcpClassIdentifier
.Header
.Length
= sizeof (DHCPV4_CLASS_ID_DATA
);
198 DHCPOpStart
.DhcpClassIdentifier
.Data
.ClassIdentifier
,
200 sizeof ("PXEClient:")
202 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.Lit2
, "Arch:", sizeof ("Arch:"));
204 DHCPOpStart
.DhcpClassIdentifier
.Data
.ArchitectureType
,
208 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.Lit3
, ":", sizeof (":"));
209 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.InterfaceName
, "XXXX", sizeof ("XXXX"));
210 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.Lit4
, ":", sizeof (":"));
211 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.UndiMajor
, "yyy", sizeof ("yyy"));
212 CopyMem (DHCPOpStart
.DhcpClassIdentifier
.Data
.UndiMinor
, "xxx", sizeof ("xxx"));
213 DHCPOpStart
.End
[0] = OP_END
;
216 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
219 // DHCPDECLINE option structure
221 struct opdeclinestr
{
223 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType
;
224 struct requestopendstr OpDeclineEnd
;
227 #define DHCPDECLINEoptions (*(struct opdeclinestr *) DHCPV4_TRANSMIT_BUFFER.options)
230 // DHCPRELEASE option structure
232 struct opreleasestr
{
234 DHCPV4_OP_MESSAGE_TYPE DhcpMessageType
;
235 DHCPV4_OP_SERVER_IP DhcServerIpPtr
;
239 #define DHCPRELEASEoptions (*(struct opreleasestr *) DHCPV4_TRANSMIT_BUFFER.options)
242 // array of PXE vendor options in which we are interested
243 // value 0 -> not of interest, else value is index into PXE OPTION array
244 // option values from 1 to MAX_OUR_PXE_OPT
246 STATIC UINT8 ourPXEopts
[MAX_OUR_PXE_OPT
] = {
247 VEND_PXE_MTFTP_IP_IX
, // multicast IP address of bootfile for MTFTP listen
248 VEND_PXE_MTFTP_CPORT_IX
, // UDP Port to monitor for MTFTP responses - Intel order
249 VEND_PXE_MTFTP_SPORT_IX
, // Server UDP Port for MTFTP open - Intel order
250 VEND_PXE_MTFTP_TMOUT_IX
, // Listen timeout - secs
251 VEND_PXE_MTFTP_DELAY_IX
, // Transmission timeout - secs
252 VEND_PXE_DISCOVERY_CONTROL_IX
, // bit field
253 VEND_PXE_DISCOVERY_MCAST_ADDR_IX
, // boot server discovery multicast address
254 VEND_PXE_BOOT_SERVERS_IX
, // list of boot servers of form tp(2) cnt(1) ips[cnt]
255 VEND_PXE_BOOT_MENU_IX
,
256 VEND_PXE_BOOT_PROMPT_IX
,
257 VEND_PXE_MCAST_ADDRS_ALLOC_IX
, // not used by client
258 VEND_PXE_CREDENTIAL_TYPES_IX
,
259 VEND_13_IX
, // not used by client
260 VEND_14_IX
, // not used by client
261 VEND_15_IX
, // not used by client
262 VEND_16_IX
, // not used by client
263 VEND_17_IX
, // not used by client
264 VEND_18_IX
, // not used by client
265 VEND_19_IX
, // not used by client
266 VEND_20_IX
, // not used by client
267 VEND_21_IX
, // not used by client
268 VEND_22_IX
, // not used by client
269 VEND_23_IX
, // not used by client
270 VEND_24_IX
, // not used by client
271 VEND_25_IX
, // not used by client
272 VEND_26_IX
, // not used by client
273 VEND_27_IX
, // not used by client
274 VEND_28_IX
, // not used by client
275 VEND_29_IX
, // not used by client
276 VEND_30_IX
, // not used by client
277 VEND_31_IX
, // not used by client
278 VEND_32_IX
, // not used by client
279 VEND_33_IX
, // not used by client
280 VEND_34_IX
, // not used by client
281 VEND_35_IX
, // not used by client
282 VEND_36_IX
, // not used by client
283 VEND_37_IX
, // not used by client
284 VEND_38_IX
, // not used by client
285 VEND_39_IX
, // not used by client
286 VEND_40_IX
, // not used by client
287 VEND_41_IX
, // not used by client
288 VEND_42_IX
, // not used by client
289 VEND_43_IX
, // not used by client
290 VEND_44_IX
, // not used by client
291 VEND_45_IX
, // not used by client
292 VEND_46_IX
, // not used by client
293 VEND_47_IX
, // not used by client
294 VEND_48_IX
, // not used by client
295 VEND_49_IX
, // not used by client
296 VEND_50_IX
, // not used by client
297 VEND_51_IX
, // not used by client
298 VEND_52_IX
, // not used by client
299 VEND_53_IX
, // not used by client
300 VEND_54_IX
, // not used by client
301 VEND_55_IX
, // not used by client
302 VEND_56_IX
, // not used by client
303 VEND_57_IX
, // not used by client
304 VEND_58_IX
, // not used by client
305 VEND_59_IX
, // not used by client
306 VEND_60_IX
, // not used by client
307 VEND_61_IX
, // not used by client
308 VEND_62_IX
, // not used by client
309 VEND_63_IX
, // not used by client
310 VEND_64_IX
, // not used by client
311 VEND_65_IX
, // not used by client
312 VEND_66_IX
, // not used by client
313 VEND_67_IX
, // not used by client
314 VEND_68_IX
, // not used by client
315 VEND_69_IX
, // not used by client
316 VEND_70_IX
, // not used by client
317 VEND_PXE_BOOT_ITEM_IX
320 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
323 // array of options in which we are interested
324 // value 0 -> not of interest, else value is index into OPTION array
325 // option values from 1 to MAX_OUR_OPT
327 STATIC UINT8 OurDhcpOptions
[MAX_OUR_OPT
] = {
328 OP_SUBNET_MASK_IX
, // OP_SUBNET_MASK 1 // data is the subnet mask
329 OP_TIME_OFFSET_IX
, // OP_TIME_OFFSET 2 // data is the time offset of subnet to UTC in seconds
330 OP_ROUTER_LIST_IX
, // OP_ROUTER_LIST 3 // list of routers on subnet
331 OP_TIME_SERVERS_IX
, // OP_TIME_SERVERS 4 // list of time servers available
332 OP_NAME_SERVERS_IX
, // OP_NAME_SERVERS 5 // list of name servers available
333 OP_DNS_SERVERS_IX
, // OP_DNS_SERVERS 6 // list of DNS servers available
334 OP_LOG_SERVERS_IX
, // OP_LOG_SERVERS 7
335 OP_COOKIE_SERVERS_IX
, // OP_COOKIE_SERVERS 8
336 OP_LPR_SREVERS_IX
, // OP_LPR_SREVERS 9
337 OP_IMPRESS_SERVERS_IX
, // OP_IMPRESS_SERVERS 10
338 OP_RES_LOC_SERVERS_IX
, // OP_RES_LOC_SERVERS 11
339 OP_HOST_NAME_IX
, // OP_HOST_NAME 12 // client name
340 OP_BOOT_FILE_SZ_IX
, // OP_BOOT_FILE_SZ 13 // number of 512 blocks of boot file
341 OP_DUMP_FILE_IX
, // OP_DUMP_FILE 14 // path name of dump file if client crashes
342 OP_DOMAIN_NAME_IX
, // OP_DOMAIN_NAME 15 // domain name to use
343 OP_SWAP_SERVER_IX
, // OP_SWAP_SERVER 16
344 OP_ROOT_PATH_IX
, // OP_ROOT_PATH 17 // path name containing root disk
345 OP_EXTENSION_PATH_IX
, // OP_EXTENSION_PATH 18 // name of TFTP downloadable file of form of OP
346 OP_IP_FORWARDING_IX
, // OP_IP_FORWARDING 19 // enable/disable IP packet forwarding
347 OP_NON_LOCAL_SRC_RTE_IX
, // OP_NON_LOCAL_SRC_RTE 20 // enable/disable non local source routing
348 OP_POLICY_FILTER_IX
, // OP_POLICY_FILTER 21 // policy filters for non local source routing
349 OP_MAX_DATAGRAM_SZ_IX
, // OP_MAX_DATAGRAM_SZ 22 // maximum datagram reassembly size
350 OP_DEFAULT_TTL_IX
, // OP_DEFAULT_TTL 23 // default IP time to live
351 OP_MTU_AGING_TIMEOUT_IX
, // OP_MTU_AGING_TIMEOUT 24
352 OP_MTU_SIZES_IX
, // OP_MTU_SIZES 25
353 OP_MTU_TO_USE_IX
, // OP_MTU_TO_USE 26
354 OP_ALL_SUBNETS_LOCAL_IX
, // OP_ALL_SUBNETS_LOCAL 27
355 OP_BROADCAST_ADD_IX
, // OP_BROADCAST_ADD 28 // broadcast address used on subnet
356 OP_PERFORM_MASK_DISCOVERY_IX
, // OP_PERFORM_MASK_DISCOVERY 29 // perform mask discovery using ICMP
357 OP_RESPOND_TO_MASK_REQ_IX
, // OP_RESPOND_TO_MASK_REQ 30 // respond to subnet mask requests using ICMP
358 OP_PERFORM_ROUTER_DISCOVERY_IX
, // OP_PERFORM_ROUTER_DISCOVERY 31
359 OP_ROUTER_SOLICIT_ADDRESS_IX
, // OP_ROUTER_SOLICIT_ADDRESS 32
360 OP_STATIC_ROUTER_LIST_IX
, // OP_STATIC_ROUTER_LIST 33 // list of dest/route pairs
361 OP_USE_ARP_TRAILERS_IX
, // OP_USE_ARP_TRAILERS 34
362 OP_ARP_CACHE_TIMEOUT_IX
, // OP_ARP_CACHE_TIMEOUT 35
363 OP_ETHERNET_ENCAPSULATION_IX
, // OP_ETHERNET_ENCAPSULATION 36 // 0 -> RFC 894, 1 -> IEEE 802.3 (RFC 1042)
364 OP_TCP_DEFAULT_TTL_IX
, // OP_TCP_DEFAULT_TTL 37 // default time to live when sending TCP segments
365 OP_TCP_KEEP_ALIVE_INT_IX
, // OP_TCP_KEEP_ALIVE_INT 38 // keep alive interval in seconds
366 OP_KEEP_ALIVE_GARBAGE_IX
, // OP_KEEP_ALIVE_GARBAGE 39
367 OP_NIS_DOMAIN_NAME_IX
, // OP_NIS_DOMAIN_NAME 40
368 OP_NIS_SERVERS_IX
, // OP_NIS_SERVERS 41
369 OP_NTP_SERVERS_IX
, // OP_NTP_SERVERS 42
370 OP_VENDOR_SPECIFIC_IX
, // OP_VENDOR_SPECIFIC 43
371 OP_NBNS_SERVERS_IX
, // OP_NBNS_SERVERS 44
372 OP_NBDD_SERVERS_IX
, // OP_NBDD_SERVERS 45
373 OP_NETBIOS_NODE_TYPE_IX
, // OP_NETBIOS_NODE_TYPE 46
374 OP_NETBIOS_SCOPE_IX
, // OP_NETBIOS_SCOPE 47
375 OP_XWINDOW_SYSTEM_FONT_SERVERS_IX
, // OP_XWINDOW_SYSTEM_FONT_SERVERS 48
376 OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS_IX
, // OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49
377 OP_DHCP_REQ_IP_ADD_IX
, // OP_DHCP_REQ_IP_ADD 50 // requested IP address - in DHCPDISCOVER
378 OP_DHCP_LEASE_TIME_IX
, // OP_DHCP_LEASE_TIME 51 // lease time requested/granted
379 OP_DHCP_OPTION_OVERLOAD_IX
, // OP_DHCP_OPTION_OVERLOAD 52 // file/server name/both used to hold options
380 OP_DHCP_MESSAGE_TYPE_IX
, // OP_DHCP_MESSAGE_TYPE 53 // message type
381 OP_DHCP_SERVER_IP_IX
, // OP_DHCP_SERVER_IP 54 // IP of server
382 OP_DHCP_PARM_REQ_LIST_IX
, // OP_DHCP_PARM_REQ_LIST 55 // list of requested parameters
383 OP_DHCP_ERROR_MESSAGE_IX
, // OP_DHCP_ERROR_MESSAGE 56 // in DHCPNAK or DECLINE messages
384 OP_DHCP_MAX_MESSAGE_SZ_IX
, // OP_DHCP_MAX_MESSAGE_SZ 57 // maximum DHCP message size client will accept
385 OP_DHCP_RENEWAL_TIME_IX
, // OP_DHCP_RENEWAL_TIME 58 // time in seconds before transitioning to RENEWING state
386 OP_DHCP_REBINDING_TIME_IX
, // OP_DHCP_REBINDING_TIME 59 // time in seconds before transitioning to REBINDING state
387 OP_DHCP_CLASS_IDENTIFIER_IX
, // OP_DHCP_CLASS_IDENTIFIER 60
388 OP_DHCP_CLIENT_IDENTIFIER_IX
, // OP_DHCP_CLIENT_IDENTIFIER 61
389 OP_RESERVED62_IX
, // OP_RESERVED62
390 OP_RESERVED63_IX
, // OP_RESERVED63
391 OP_NISPLUS_DOMAIN_NAME_IX
, // OP_NISPLUS_DOMAIN_NAME 64
392 OP_NISPLUS_SERVERS_IX
, // OP_NISPLUS_SERVERS 65
393 OP_DHCP_TFTP_SERVER_NAME_IX
, // OP_DHCP_TFTP_SERVER_NAME 66
394 OP_DHCP_BOOTFILE_IX
// OP_DHCP_BOOTFILE 67
397 #define RxBuf ((DHCP_RECEIVE_BUFFER *) (Private->ReceiveBuffers))
401 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
404 PxeBcLibGetSmbiosString (
405 IN SMBIOS_STRUCTURE_POINTER
*Smbios
,
406 IN UINT16 StringNumber
410 Return SMBIOS string given the string number.
413 Smbios - Pointer to SMBIOS structure
414 StringNumber - String number to return. 0 is used to skip all strings and
415 point to the next SMBIOS structure.
418 Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == 0
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
;
458 PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
459 IN EFI_GUID
*SystemGuid
,
460 OUT CHAR8
**SystemSerialNumber
465 This function gets system guid and serial number from the smbios table
468 SystemGuid - The pointer of returned system guid
469 SystemSerialNumber - The pointer of returned system serial number
472 EFI_SUCCESS - Successfully get the system guid and system serial number
473 EFI_NOT_FOUND - Not find the SMBIOS table
477 SMBIOS_STRUCTURE_TABLE
*SmbiosTable
;
478 SMBIOS_STRUCTURE_POINTER Smbios
;
479 SMBIOS_STRUCTURE_POINTER SmbiosEnd
;
482 Status
= EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid
, (VOID
**) &SmbiosTable
);
484 if (EFI_ERROR (Status
)) {
485 return EFI_NOT_FOUND
;
488 Smbios
.Hdr
= (SMBIOS_HEADER
*) (UINTN
) SmbiosTable
->TableAddress
;
489 SmbiosEnd
.Raw
= (UINT8
*) (UINTN
) (SmbiosTable
->TableAddress
+ SmbiosTable
->TableLength
);
491 for (Index
= 0; Index
< SmbiosTable
->TableLength
; Index
++) {
492 if (Smbios
.Hdr
->Type
== 1) {
493 if (Smbios
.Hdr
->Length
< 0x19) {
495 // Older version did not support Guid and Serial number
500 // SMBIOS tables are byte packed so we need to do a byte copy to
501 // prevend alignment faults on Itanium-based platform.
503 CopyMem (SystemGuid
, &Smbios
.Type1
->Uuid
, sizeof (EFI_GUID
));
504 *SystemSerialNumber
= PxeBcLibGetSmbiosString (&Smbios
, Smbios
.Type1
->SerialNumber
);
509 // Make Smbios point to the next record
511 PxeBcLibGetSmbiosString (&Smbios
, 0);
513 if (Smbios
.Raw
>= SmbiosEnd
.Raw
) {
515 // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e.
516 // given this we must double check against the lenght of
526 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
529 // add router list to list
534 PXE_BASECODE_DEVICE
*Private
,
535 DHCPV4_OP_IP_LIST
*IpListPtr
538 EFI_IP_ADDRESS TmpIp
;
542 if (IpListPtr
== NULL
) {
546 for (Index
= 0, num
= IpListPtr
->Header
.Length
>> 2; Index
< num
; ++Index
) {
547 CopyMem (&TmpIp
, &IpListPtr
->IpList
[Index
], 4);
548 Ip4AddRouter (Private
, &TmpIp
);
552 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
555 // send ARP for our IP - fail if someone has it
560 PXE_BASECODE_DEVICE
*Private
563 EFI_MAC_ADDRESS DestMac
;
564 EFI_STATUS EfiStatus
;
566 ZeroMem (&DestMac
, sizeof DestMac
);
568 if (GetHwAddr(Private
, (EFI_IP_ADDRESS
*)&DHCP_REQ_OPTIONS
.OpReqIP
.Ip
, (EFI_MAC_ADDRESS
*)&DestMac
)
569 || DoArp(Private
, (EFI_IP_ADDRESS
*)&DHCP_REQ_OPTIONS
.OpReqIP
.Ip
, (EFI_MAC_ADDRESS
*)&DestMac
) == EFI_SUCCESS
) {
570 return FALSE
; // somebody else has this IP
574 (EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->StationIp
,
575 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
576 sizeof (EFI_IPv4_ADDRESS
)
579 Private
->GoodStationIp
= TRUE
;
581 if (!Private
->UseIgmpv1Reporting
) {
585 if (Private
->Igmpv1TimeoutEvent
!= NULL
) {
589 EfiStatus
= gBS
->CreateEvent (
594 &Private
->Igmpv1TimeoutEvent
597 if (EFI_ERROR (EfiStatus
)) {
598 Private
->Igmpv1TimeoutEvent
= NULL
;
602 EfiStatus
= gBS
->SetTimer (
603 Private
->Igmpv1TimeoutEvent
,
605 (UINT64
) V1ROUTER_PRESENT_TIMEOUT
* 10000000
608 if (EFI_ERROR (EfiStatus
)) {
609 gBS
->CloseEvent (Private
->Igmpv1TimeoutEvent
);
610 Private
->Igmpv1TimeoutEvent
= NULL
;
616 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
620 PXE_BASECODE_DEVICE
*Private
,
621 DHCP_RECEIVE_BUFFER
*RxBufPtr
626 (DHCPV4_OP_IP_LIST
*) RxBufPtr
->OpAdds
.PktOptAdds
[OP_ROUTER_LIST_IX
- 1]
630 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
634 PXE_BASECODE_DEVICE
*Private
,
635 EFI_IP_ADDRESS
*ServerIpPtr
,
636 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
637 EFI_IP_ADDRESS
*ClientIpPtr
,
638 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
643 Len
= sizeof DHCPV4_TRANSMIT_BUFFER
;
647 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
656 Private
->TransmitBuffer
660 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
663 // initialize the DHCP structure
672 PXE_BASECODE_DEVICE
*Private
677 CHAR8
*SystemSerialNumber
;
678 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
680 PxebcMode
= Private
->EfiBc
.Mode
;
682 ZeroMem (&DHCPV4_TRANSMIT_BUFFER
, sizeof (DHCPV4_STRUCT
));
683 DHCPV4_TRANSMIT_BUFFER
.op
= BOOTP_REQUEST
;
684 DHCPV4_TRANSMIT_BUFFER
.htype
= Private
->SimpleNetwork
->Mode
->IfType
;
685 DHCPV4_TRANSMIT_BUFFER
.flags
= HTONS (DHCP_BROADCAST_FLAG
);
686 CopyMem (&DHCPV4_OPTIONS_BUFFER
, (VOID
*) &DHCPOpStart
, sizeof (DHCPOpStart
));
689 // default to hardware address
691 HwAddrLen
= Private
->SimpleNetwork
->Mode
->HwAddressSize
;
693 if (HwAddrLen
> sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
) {
694 HwAddrLen
= sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
;
697 String
= (UINT8
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
;
699 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
700 (EFI_GUID
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
,
703 if (PxebcMode
->SendGUID
) {
704 HwAddrLen
= sizeof (EFI_GUID
);
705 String
= (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
;
709 // GUID not yet set - send all 0xff's to show programable (via SetVariable)
710 // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);
711 // GUID not yet set - send all 0's to show not programable
713 ZeroMem (DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
, sizeof (EFI_GUID
));
716 DHCPV4_TRANSMIT_BUFFER
.hlen
= (UINT8
) HwAddrLen
;
717 CopyMem (DHCPV4_TRANSMIT_BUFFER
.chaddr
, String
, HwAddrLen
);
721 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
,
722 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
725 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.Type
= Private
->NiiPtr
->Type
;
726 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
= Private
->NiiPtr
->MajorVer
;
727 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
= Private
->NiiPtr
->MinorVer
;
729 *(C4Str
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.InterfaceName
= *(C4Str
*) Private
->NiiPtr
->StringId
;
732 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
,
733 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
,
734 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
738 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
,
739 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
,
740 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
744 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
748 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
761 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
774 LocalPtr
.BytePtr
= ptr
;
775 if (Op
<= MAX_OUR_PXE_OPT
) {
776 Index
= ourPXEopts
[Op
- 1];
778 RxBufPtr
->OpAdds
.PxeOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
779 status
|= 1 << Index
;
780 if (Index
== VEND_PXE_BOOT_ITEM
&& LocalPtr
.BootItem
->Header
.Length
== 3) {
781 RxBufPtr
->OpAdds
.Status
|= USE_THREE_BYTE
;
792 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
796 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
806 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
819 LocalPtr
.BytePtr
= ptr
;
820 if (Op
<= MAX_OUR_OPT
) {
821 Index
= OurDhcpOptions
[Op
- 1];
823 RxBufPtr
->OpAdds
.PktOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
824 if (Index
== OP_VENDOR_SPECIFIC_IX
) {
826 status
= DecodePxeOptions (
828 (UINT8
*) LocalPtr
.VendorOptions
->VendorOptions
,
829 LocalPtr
.VendorOptions
->Header
.Length
832 RxBufPtr
->OpAdds
.Status
|= PXE_TYPE
;
834 // check for all the MTFTP info options present - any missing is a nogo
836 if ((status
& WfM11a_OPTS
) == WfM11a_OPTS
) {
837 RxBufPtr
->OpAdds
.Status
|= WfM11a_TYPE
;
840 if (status
& DISCOVER_OPTS
) {
841 RxBufPtr
->OpAdds
.Status
|= DISCOVER_TYPE
;
844 if (status
& CREDENTIALS_OPT
) {
845 RxBufPtr
->OpAdds
.Status
|= CREDENTIALS_TYPE
;
856 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
860 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
869 SetMem (&RxBufPtr
->OpAdds
, sizeof RxBufPtr
->OpAdds
, 0);
873 RxBufPtr
->u
.Dhcpv4
.options
+ 4,
874 Len
- (sizeof RxBufPtr
->u
.Dhcpv4
- sizeof RxBufPtr
->u
.Dhcpv4
.options
+ 4)
877 LocalPtr
.OpPtr
= RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_OPTION_OVERLOAD_IX
- 1];
879 if ((LocalPtr
.OpPtr
) && (LocalPtr
.Overload
->Overload
& OVLD_SRVR_NAME
)) {
880 DecodeOptions (RxBufPtr
, RxBufPtr
->u
.Dhcpv4
.sname
, sizeof RxBufPtr
->u
.Dhcpv4
.sname
);
883 if (LocalPtr
.OpPtr
&& (LocalPtr
.Overload
->Overload
& OVLD_FILE
)) {
884 DecodeOptions (RxBufPtr
, RxBufPtr
->u
.Dhcpv4
.file
, sizeof RxBufPtr
->u
.Dhcpv4
.file
);
885 } else if (!RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] && RxBufPtr
->u
.Dhcpv4
.file
[0]) {
886 RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] = (DHCPV4_OP_STRUCT
*) (RxBufPtr
->u
.Dhcpv4
.file
- sizeof (DHCPV4_OP_HEADER
));
888 RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]->Header
.Length
= (UINT8
) AsciiStrLen ((CHAR8
*)RxBufPtr
->u
.Dhcpv4
.file
);
891 LocalPtr
.OpPtr
= RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_CLASS_IDENTIFIER_IX
- 1];
893 if ((LocalPtr
.OpPtr
) &&
894 LocalPtr
.PxeClassStr
->Header
.Length
>= 9 &&
895 !CompareMem (LocalPtr
.PxeClassStr
->Class
, "PXEClient", 9)
897 RxBufPtr
->OpAdds
.Status
|= PXE_TYPE
;
901 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
905 PXE_BASECODE_DEVICE
*Private
,
910 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
912 RxBufPtr
= &((DHCP_RECEIVE_BUFFER
*) Private
->DhcpPacketBuffer
)[PacketIndex
];
916 &RxBuf
[RxBufIndex
].u
.Dhcpv4
,
917 sizeof (RxBuf
[RxBufIndex
].u
.Dhcpv4
)
920 Parse (RxBufPtr
, sizeof RxBufPtr
->u
.ReceiveBuffer
);
923 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
927 PXE_BASECODE_DEVICE
*Private
,
931 Private
->EfiBc
.Mode
->ProxyOfferReceived
= TRUE
;
932 CopyParseRxBuf (Private
, RxBufIndex
, PXE_OFFER_INDEX
);
935 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
939 PXE_BASECODE_DEVICE
*Private
,
940 EFI_PXE_BASE_CODE_PACKET
*PacketPtr
,
941 EFI_PXE_BASE_CODE_PACKET
*NewPacketPtr
,
945 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
947 DhcpRxBuf
= &((DHCP_RECEIVE_BUFFER
*) Private
->DhcpPacketBuffer
)[Index
];
950 (EFI_PXE_BASE_CODE_PACKET
*) &DhcpRxBuf
->u
.Dhcpv4
,
952 sizeof (*NewPacketPtr
)
955 CopyMem (&*PacketPtr
, &*NewPacketPtr
, sizeof (*NewPacketPtr
));
957 Parse (DhcpRxBuf
, sizeof DhcpRxBuf
->u
.ReceiveBuffer
);
960 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
964 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
969 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
973 // if a DHCP type, must be DHCPOFFER and must have server id
978 (LocalPtr
.MessageType
->Type
== DHCPACK
) &&
979 DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]
983 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
986 // if a discover type packet, make sure all required fields are present
991 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
994 PXE_OP_SERVER_LIST
*BootServerOpPtr
;
997 if ((DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) == 0) {
1001 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
1003 if (LocalPtr
.OpPtr
== NULL
) {
1004 LocalPtr
.OpPtr
= (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
1005 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
1008 // make sure all required fields are here
1009 // if mucticast enabled, need multicast address
1011 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
) &&
1012 (!DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1] || !IS_MULTICAST (((DHCPV4_OP_STRUCT
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1])->Data
))
1016 // missing required field
1020 // if a list, it better be good
1022 BootServerOpPtr
= (PXE_OP_SERVER_LIST
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1];
1024 if (BootServerOpPtr
!= NULL
) {
1025 PXE_SERVER_LIST
*BootServerListPtr
;
1027 INTN ServerEntryLen
;
1029 BootServerListPtr
= BootServerOpPtr
->ServerList
;
1030 ServerListLen
= BootServerOpPtr
->Header
.Length
;
1033 EFI_IPv4_ADDRESS
*IpListPtr
;
1036 IpCnt
= BootServerListPtr
->u
.Ipv4List
.IpCount
;
1038 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (IpCnt
- 1) * sizeof (EFI_IPv4_ADDRESS
);
1040 if (ServerListLen
< ServerEntryLen
) {
1042 // missing required field
1047 IpListPtr
= BootServerListPtr
->u
.Ipv4List
.IpList
;
1050 if (IS_MULTICAST (IpListPtr
)) {
1052 // missing required field
1060 BootServerListPtr
= (PXE_SERVER_LIST
*) IpListPtr
;
1061 } while (ServerListLen
-= ServerEntryLen
);
1064 // else there must be a list if use list enabled or multicast and
1065 // broadcast disabled
1067 else if ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) ||
1068 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
1071 // missing required field
1076 // if not USE_BOOTFILE or no bootfile given, must have menu stuff
1078 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& USE_BOOTFILE
) ||
1079 !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1083 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_MENU_IX
- 1];
1085 if (LocalPtr
.OpPtr
== NULL
|| !DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_PROMPT_IX
- 1]) {
1087 // missing required field
1092 // make sure menu valid
1094 MenuLth
= LocalPtr
.BootMenu
->Header
.Length
;
1095 LocalPtr
.BootMenuItem
= LocalPtr
.BootMenu
->MenuItem
;
1100 MenuItemLen
= LocalPtr
.BootMenuItem
->DataLen
;
1102 if (MenuItemLen
== 0) {
1104 // missing required field
1109 MenuItemLen
+= sizeof (*LocalPtr
.BootMenuItem
) - sizeof (LocalPtr
.BootMenuItem
->Data
);
1111 MenuLth
-= MenuItemLen
;
1112 LocalPtr
.BytePtr
+= MenuItemLen
;
1113 } while (MenuLth
> 0);
1117 // missing required field
1123 if (!DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
1124 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultBootItem
;
1130 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1134 DHCP_RECEIVE_BUFFER
*RxBufPtr
1137 return (BOOLEAN
) (DHCPOfferAckEdit (RxBufPtr
) ? AckEdit (RxBufPtr
) : FALSE
);
1140 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1148 PXE_BASECODE_DEVICE
*Private
,
1149 BOOLEAN (*ExtraEdit
)(DHCP_RECEIVE_BUFFER
*DhcpRxBuf
),
1150 UINT16 OpFlags
, // for Udp read
1151 EFI_IP_ADDRESS
*ServerIpPtr
,
1152 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
1153 EFI_IP_ADDRESS
*ClientIpPtr
,
1154 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
,
1155 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
,
1156 EFI_EVENT TimeoutEvent
1159 Routine description:
1160 Wait for an OFFER/ACK packet.
1163 Private := Pointer to PxeBc interface
1164 ExtraEdit := Pointer to extra option checking function
1165 OpFlags := UdpRead() option flags
1176 EFI_IP_ADDRESS ServerIp
;
1177 EFI_STATUS StatCode
;
1182 // Wait until we get a UDP packet.
1184 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1185 RxBufLen
= sizeof RxBuf
[0].u
.ReceiveBuffer
;
1187 if ((StatCode
= UdpRead (
1196 (UINTN
*) &RxBufLen
,
1197 &DhcpRxBuf
->u
.Dhcpv4
,
1199 )) != EFI_SUCCESS
) {
1200 if (StatCode
== EFI_TIMEOUT
) {
1201 StatCode
= EFI_NO_RESPONSE
;
1207 // got a packet - see if a good offer
1209 if (DhcpRxBuf
->u
.Dhcpv4
.op
!= BOOTP_REPLY
) {
1213 if (DhcpRxBuf
->u
.Dhcpv4
.xid
!= DHCPV4_TRANSMIT_BUFFER
.xid
) {
1217 if (*(UINT32
*) DHCPV4_TRANSMIT_BUFFER
.options
!= * (UINT32
*) DhcpRxBuf
->u
.Dhcpv4
.options
) {
1221 if (*(UINT8
*) &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
> 223) {
1226 DhcpRxBuf
->u
.Dhcpv4
.chaddr
,
1227 DHCPV4_TRANSMIT_BUFFER
.chaddr
,
1228 sizeof DhcpRxBuf
->u
.Dhcpv4
.chaddr
1236 Parse (DhcpRxBuf
, RxBufLen
);
1238 if (!(*ExtraEdit
) (DhcpRxBuf
)) {
1242 // Good DHCP packet.
1244 StatCode
= EFI_SUCCESS
;
1251 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1259 PXE_BASECODE_DEVICE
*Private
1262 EFI_IP_ADDRESS ClientIp
;
1263 EFI_IP_ADDRESS ServerIp
;
1264 EFI_STATUS StatCode
;
1265 EFI_EVENT TimeoutEvent
;
1272 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1275 for (Index
= 0; Index
< (sizeof Private
->ServerCount
) / sizeof Private
->ServerCount
[0]; ++Index
) {
1276 Private
->ServerCount
[Index
] = 0;
1277 Private
->GotProxy
[Index
] = 0;
1280 Private
->GotBootp
= 0;
1282 // these we throw away
1284 Private
->GotProxy
[DHCP_ONLY_IX
] = 1;
1285 StatCode
= gBS
->CreateEvent (
1293 if (EFI_ERROR (StatCode
)) {
1297 StatCode
= gBS
->SetTimer (
1300 Private
->Timeout
* 10000000 + 1000000
1303 if (EFI_ERROR (StatCode
)) {
1304 gBS
->CloseEvent (TimeoutEvent
);
1311 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1314 DhcpRxBuf
= &RxBuf
[NumOffers
];
1317 StatCode
= GetOfferAck (
1320 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
|
1321 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
|
1322 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1335 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
1338 // check type of offer
1340 if (LocalPtr
.OpPtr
== NULL
) {
1342 // bootp - we only need one and make sure has bootfile
1344 if (Private
->GotBootp
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1348 Private
->GotBootp
= (UINT8
) (NumOffers
+ 1);
1351 // if a DHCP type, must be DHCPOFFER and must have server id
1353 else if (LocalPtr
.MessageType
->Type
!= DHCPOFFER
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]) {
1359 // get type - PXE10, WfM11a, or BINL
1361 if (DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) {
1363 } else if (DhcpRxBuf
->OpAdds
.Status
& WfM11a_TYPE
) {
1365 // WfM - make sure it has a bootfile
1367 if (!DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1373 TypeIx
= (DhcpRxBuf
->OpAdds
.Status
& PXE_TYPE
) ? BINL_IX
: DHCP_ONLY_IX
;
1376 // check DHCP or proxy
1378 if (DhcpRxBuf
->u
.Dhcpv4
.yiaddr
== 0) {
1380 // proxy - only need one of each type if not BINL
1381 // and must have at least PXE_TYPE
1383 if (TypeIx
== BINL_IX
) {
1384 Private
->BinlProxies
[Private
->GotProxy
[BINL_IX
]++] = (UINT8
) NumOffers
;
1385 } else if (Private
->GotProxy
[TypeIx
]) {
1388 Private
->GotProxy
[TypeIx
] = (UINT8
) (NumOffers
+ 1);
1391 Private
->OfferCount
[TypeIx
][Private
->ServerCount
[TypeIx
]++] = (UINT8
) NumOffers
;
1395 if (++NumOffers
== MAX_OFFERS
) {
1400 gBS
->CloseEvent (TimeoutEvent
);
1401 Private
->NumOffersReceived
= NumOffers
;
1403 return (Private
->NumOffersReceived
) ? EFI_SUCCESS
: EFI_NO_RESPONSE
;
1406 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1414 PXE_BASECODE_DEVICE
*Private
1417 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1420 PxebcMode
= Private
->EfiBc
.Mode
;
1421 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1423 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1424 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1426 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opdeclinestr
),
1427 sizeof (DHCPOpStart
) - sizeof (struct opdeclinestr
),
1430 DHCPDECLINEoptions
.DhcpMessageType
.Type
= DHCPDECLINE
;
1431 CopyMem (&DHCPDECLINEoptions
.OpDeclineEnd
, &DHCP_REQ_OPTIONS
, sizeof (struct requestopendstr
));
1432 // DHCPDECLINEoptions.OpDeclineEnd = DHCP_REQ_OPTIONS;
1435 EFI_IP_ADDRESS TmpIp
;
1437 CopyMem (&TmpIp
, &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1443 &PxebcMode
->StationIp
,
1448 InitDhcpv4TxBuf (Private
);
1449 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1450 Private
->GoodStationIp
= FALSE
;
1453 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1461 PXE_BASECODE_DEVICE
*Private
1464 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1466 DHCPV4_OP_SERVER_IP
*Point
;
1468 PxebcMode
= Private
->EfiBc
.Mode
;
1469 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1470 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1473 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opreleasestr
),
1474 sizeof (DHCPOpStart
) - sizeof (struct opreleasestr
),
1478 DHCPRELEASEoptions
.DhcpMessageType
.Type
= DHCPRELEASE
;
1479 Point
= (DHCPV4_OP_SERVER_IP
*) DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1];
1481 &DHCPRELEASEoptions
.DhcServerIpPtr
,
1483 sizeof DHCPRELEASEoptions
.DhcServerIpPtr
1486 DHCPRELEASEoptions
.End
[0] = OP_END
;
1489 EFI_IP_ADDRESS TmpIp
;
1491 CopyMem (&TmpIp
, &DHCPRELEASEoptions
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1497 &PxebcMode
->StationIp
,
1502 InitDhcpv4TxBuf (Private
);
1504 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1505 Private
->GoodStationIp
= FALSE
;
1509 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1513 PXE_BASECODE_DEVICE
*Private
,
1514 EFI_IP_ADDRESS
*ServerIpPtr
1517 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1518 EFI_STATUS StatCode
;
1519 EFI_EVENT TimeoutEvent
;
1524 StatCode
= gBS
->CreateEvent (
1532 if (EFI_ERROR (StatCode
)) {
1536 StatCode
= gBS
->SetTimer (
1539 Private
->Timeout
* 10000000 + 1000000
1542 if (EFI_ERROR (StatCode
)) {
1543 gBS
->CloseEvent (TimeoutEvent
);
1549 DhcpRxBuf
= &PXE_BINL_BUFFER
;
1552 EFI_PXE_BASE_CODE_UDP_PORT BINLSrvPort
;
1559 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1562 &Private
->EfiBc
.Mode
->StationIp
,
1563 &PSEUDO_DHCP_CLIENT_PORT
,
1570 // make sure from whom we wanted
1572 if (!DhcpRxBuf
->u
.Dhcpv4
.yiaddr
&& !CompareMem (
1574 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1575 sizeof (ServerIpPtr
->v4
)
1577 gBS
->CloseEvent (TimeoutEvent
);
1579 // got an ACK from server
1585 gBS
->CloseEvent (TimeoutEvent
);
1589 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1592 // make sure we can get BINL
1593 // send DHCPREQUEST to PXE server
1598 PXE_BASECODE_DEVICE
*Private
,
1602 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1603 EFI_IP_ADDRESS ServerIp
;
1607 DhcpRxBuf
= &RxBuf
[OfferIx
];
1610 // send DHCP request
1611 // if fail return false
1614 ((EFI_IPv4_ADDRESS
*) &ServerIp
),
1615 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1616 sizeof (EFI_IPv4_ADDRESS
)
1620 // client IP address - filled in by client if it knows it
1623 ((EFI_IPv4_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
),
1624 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1625 sizeof (EFI_IPv4_ADDRESS
)
1628 SetMem (&DHCP_REQ_OPTIONS
, sizeof DHCP_REQ_OPTIONS
, OP_PAD
);
1629 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1630 DHCPV4_OPTIONS_BUFFER
.End
[0] = OP_END
;
1631 AddRouters (Private
, DhcpRxBuf
);
1632 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1634 for (Index
= 0; Index
< 3; Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Index
) {
1635 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
1638 // unicast DHCPREQUEST to PXE server
1643 &PseudoDhcpServerPort
,
1644 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1645 &PSEUDO_DHCP_CLIENT_PORT
1650 if (!GetBINLAck (Private
, &ServerIp
)) {
1654 // early exit failures
1655 // make sure a good ACK
1657 if (!DHCPOfferAckEdit (&PXE_BINL_BUFFER
) || (
1658 !(PXE_BINL_BUFFER
.OpAdds
.Status
& DISCOVER_TYPE
) && !PXE_BINL_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1664 Private
->EfiBc
.Mode
->ProxyOfferReceived
= TRUE
;
1668 // failed - reset seconds field, etc.
1670 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1674 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1678 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1682 PXE_BASECODE_DEVICE
*Private
,
1686 if (TryBINL (Private
, OfferIx
)) {
1690 return Release (Private
);
1693 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1696 TryFinishProxyBINL (
1697 PXE_BASECODE_DEVICE
*Private
1702 for (Index
= 0; Index
< Private
->GotProxy
[BINL_IX
]; ++Index
) {
1703 if (TryBINL (Private
, Private
->BinlProxies
[Index
])) {
1708 return Release (Private
);
1711 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1714 // try to finish DORA - send DHCP request, wait for ACK, check with ARP
1719 PXE_BASECODE_DEVICE
*Private
,
1723 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1724 EFI_IP_ADDRESS ClientIp
;
1725 EFI_IP_ADDRESS ServerIp
;
1726 EFI_STATUS StatCode
;
1728 EFI_EVENT TimeoutEvent
;
1731 // send DHCP request
1732 // if fail return false
1734 DhcpRxBuf
= &DHCPV4_ACK_BUFFER
;
1735 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
1736 CopyMem (&DHCP_REQ_OPTIONS
, &RequestOpEndStr
, sizeof (RequestOpEndStr
));
1737 // DHCP_REQ_OPTIONS = RequestOpEndStr;
1738 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[OfferIx
].u
.Dhcpv4
.yiaddr
;
1741 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1742 &((DHCPV4_OP_SERVER_IP
*) RxBuf
[OfferIx
].OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1743 sizeof DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
1747 Private
->EfiBc
.Mode
->SubnetMask
.Addr
,
1753 // broadcast DHCPREQUEST
1759 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1767 StatCode
= gBS
->CreateEvent (
1775 if (EFI_ERROR (StatCode
)) {
1779 StatCode
= gBS
->SetTimer (
1782 Private
->Timeout
* 10000000 + 1000000
1785 if (EFI_ERROR (StatCode
)) {
1786 gBS
->CloseEvent (TimeoutEvent
);
1796 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
,
1807 // check type of response - need DHCPACK
1810 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1811 &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
,
1812 sizeof (EFI_IPv4_ADDRESS
)
1814 &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
,
1815 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1816 sizeof (EFI_IPv4_ADDRESS
)
1822 // check with ARP that IP unused - good return true
1824 if (!SetStationIP (Private
)) {
1826 // fail - send DHCPDECLINE and return false
1828 DeclineOffer (Private
);
1832 LocalPtr
.OpPtr
= DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1834 if (LocalPtr
.OpPtr
!= NULL
) {
1836 (EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
,
1837 &LocalPtr
.SubnetMaskStr
->Ip
,
1838 sizeof (EFI_IPv4_ADDRESS
)
1842 AddRouters (Private
, DhcpRxBuf
);
1843 gBS
->CloseEvent (TimeoutEvent
);
1847 gBS
->CloseEvent (TimeoutEvent
);
1851 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1854 // try a DHCP server of appropriate type
1859 PXE_BASECODE_DEVICE
*Private
,
1866 // go through the DHCP servers of the requested type
1868 for (Index
= 0; Index
< Private
->ServerCount
[TypeIx
]; ++Index
) {
1869 if (TryFinishDORA (Private
, Index
= Private
->OfferCount
[TypeIx
][Index
])) {
1870 if (TypeIx
== BINL_IX
&& !TryFinishBINL (Private
, Index
)) {
1881 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1884 // try a DHCP only server and a proxy of appropriate type
1888 TryProxyFinishDORA (
1889 PXE_BASECODE_DEVICE
*Private
,
1895 if (!Private
->GotProxy
[TypeIx
]) {
1897 // no proxies of the type wanted
1902 // go through the DHCP only servers
1904 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1905 if (TryFinishDORA (Private
, Private
->OfferCount
[DHCP_ONLY_IX
][Index
])) {
1906 if (TypeIx
!= BINL_IX
) {
1907 CopyProxyRxBuf (Private
, Private
->GotProxy
[TypeIx
] - 1);
1908 } else if (!TryFinishProxyBINL (Private
)) {
1910 // if didn't work with this DHCP, won't work with any
1922 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1925 // getting to the bottom of the barrel
1929 TryAnyWithBootfileFinishDORA (
1930 PXE_BASECODE_DEVICE
*Private
1934 // try a DHCP only server who has a bootfile
1939 for (Index
= 0; Index
< Private
->ServerCount
[DHCP_ONLY_IX
]; ++Index
) {
1942 offer
= Private
->OfferCount
[DHCP_ONLY_IX
][Index
];
1944 if (RxBuf
[offer
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] && TryFinishDORA (Private
, offer
)) {
1949 // really at bottom - see if be have any bootps
1951 if (!Private
->GotBootp
) {
1955 DHCP_REQ_OPTIONS
.OpReqIP
.Ip
= *(EFI_IPv4_ADDRESS
*) &RxBuf
[Private
->GotBootp
- 1].u
.Dhcpv4
.yiaddr
;
1957 if (!SetStationIP (Private
)) {
1961 // treat BOOTP response as DHCP ACK packet
1963 CopyParseRxBuf (Private
, Private
->GotBootp
- 1, DHCPV4_ACK_INDEX
);
1965 LocalPtr
.OpPtr
= RxBuf
[Private
->GotBootp
- 1].OpAdds
.PktOptAdds
[OP_SUBNET_MASK_IX
- 1];
1967 if (LocalPtr
.OpPtr
!= NULL
) {
1968 *(EFI_IPv4_ADDRESS
*) &Private
->EfiBc
.Mode
->SubnetMask
= LocalPtr
.SubnetMaskStr
->Ip
;
1974 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1981 PXE_BASECODE_DEVICE
*Private
,
1985 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
1986 EFI_STATUS StatCode
;
1989 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
| EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST
;
1992 Filter
.reserved
= 0;
1995 // set filter unicast or broadcast
1997 if ((StatCode
= IpFilter (Private
, &Filter
)) != EFI_SUCCESS
) {
2001 // seed random number with hardware address
2003 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2005 for (Private
->Timeout
= 1;
2006 Private
->Timeout
< 17;
2007 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), Private
->Timeout
<<= 1
2011 InitDhcpv4TxBuf (Private
);
2012 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2013 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2016 // broadcast DHCPDISCOVER
2018 StatCode
= DoUdpWrite (
2022 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2026 if (StatCode
!= EFI_SUCCESS
) {
2031 &Private
->EfiBc
.Mode
->DhcpDiscover
,
2032 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2033 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2039 if ((StatCode
= GetOffers (Private
)) != EFI_SUCCESS
) {
2040 if (StatCode
!= EFI_NO_RESPONSE
) {
2047 // select offer and reply DHCPREQUEST
2050 if (TryDHCPFinishDORA(Private
, PXE10_IX
) || // try DHCP with PXE10
2051 TryDHCPFinishDORA(Private
, WfM11a_IX
) || // no - try with WfM
2052 TryProxyFinishDORA(Private
, PXE10_IX
) || // no - try DHCP only and proxy with PXE10
2053 TryProxyFinishDORA(Private
, WfM11a_IX
) || // no - try DHCP only and proxy with WfM
2054 TryDHCPFinishDORA(Private
, BINL_IX
) || // no - try with WfM
2055 TryProxyFinishDORA(Private
, BINL_IX
) || // no - try DHCP only and proxy with PXE10
2056 TryAnyWithBootfileFinishDORA(Private
))
2066 NumOffers
= Private
->NumOffersReceived
;
2068 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2072 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
) {
2076 // check if a bootp server
2078 if (!RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1]) {
2080 // it is - just check ARP
2082 if (!SetStationIP (Private
)) {
2087 // else check if a DHCP only server
2089 else if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
))) {
2091 // it is a normal DHCP offer (without any PXE options), just finish the D.O.R.A by sending DHCP request.
2093 if (!TryFinishDORA (Private
, Index
)) {
2096 } else if (TryFinishDORA (Private
, Index
)) {
2097 if (!(RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) && !TryFinishBINL (Private
, Index
)) {
2102 DEBUG ((EFI_D_WARN
, "\nDoDhcpDora() Got packets. "));
2106 // now look for DHCP onlys and a Proxy
2108 for (Index
= 0; Index
< NumOffers
; ++Index
) {
2112 // ignore proxies, bootps, non DHCP onlys, and bootable DHCPS
2114 if (!RxBuf
[Index
].u
.Dhcpv4
.yiaddr
||
2115 !RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1] ||
2116 RxBuf
[Index
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
| PXE_TYPE
) ||
2117 RxBuf
[Index
].OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
2122 // found non bootable DHCP only - try to find a proxy
2124 for (Index2
= 0; Index2
< NumOffers
; ++Index2
) {
2125 if (!RxBuf
[Index2
].u
.Dhcpv4
.yiaddr
) {
2126 if (!TryFinishDORA (Private
, Index
)) {
2133 if (RxBuf
[Index2
].OpAdds
.Status
& (DISCOVER_TYPE
| WfM11a_TYPE
)) {
2134 CopyProxyRxBuf (Private
, Index2
);
2135 } else if (!TryFinishBINL (Private
, Index2
)) {
2139 DEBUG ((EFI_D_WARN
, "\nDoDhcpDora() Got packets. "));
2146 return EFI_NO_RESPONSE
;
2149 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2152 // determine if the server ip is in the ip list
2157 EFI_IP_ADDRESS
*ServerIpPtr
,
2158 PXE_SERVER_LISTS
*ServerListPtr
2163 if (!ServerListPtr
|| !ServerListPtr
->Ipv4List
.IpCount
) {
2167 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2170 &ServerListPtr
->Ipv4List
.IpList
[Index
],
2171 sizeof (EFI_IPv4_ADDRESS
)
2180 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2183 ExtractBootServerList (
2185 DHCPV4_OP_STRUCT
*ptr
,
2186 PXE_SERVER_LISTS
**ServerListPtr
2192 LocalPtr
.OpPtr
= ptr
;
2193 ServerListLen
= LocalPtr
.BootServersStr
->Header
.Length
;
2198 LocalPtr
.BootServerList
= LocalPtr
.BootServersStr
->ServerList
;
2200 while (ServerListLen
) {
2201 INTN ServerEntryLen
;
2203 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (LocalPtr
.BootServerList
->u
.Ipv4List
.IpCount
- 1) *
2204 sizeof (EFI_IPv4_ADDRESS
);
2206 if (NTOHS (LocalPtr
.BootServerList
->Type
) == Type
) {
2207 *ServerListPtr
= &LocalPtr
.BootServerList
->u
;
2211 (LocalPtr
.BytePtr
) += ServerEntryLen
;
2212 ServerListLen
-= ServerEntryLen
;
2218 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2222 PXE_BASECODE_DEVICE
*Private
2225 if (Private
->TransmitBuffer
!= NULL
) {
2226 FreePool (Private
->TransmitBuffer
);
2227 Private
->TransmitBuffer
= NULL
;
2230 if (Private
->ReceiveBuffers
!= NULL
) {
2231 FreePool (Private
->ReceiveBuffers
);
2232 Private
->ReceiveBuffers
= NULL
;
2236 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2240 PXE_BASECODE_DEVICE
*Private
2244 if (Private
->DhcpPacketBuffer
== NULL
) {
2245 Private
->DhcpPacketBuffer
= AllocatePool (sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1));
2246 if (Private
->DhcpPacketBuffer
== NULL
) {
2252 Private
->TransmitBuffer
= AllocatePool (sizeof (EFI_PXE_BASE_CODE_PACKET
));
2253 if (Private
->TransmitBuffer
== NULL
) {
2254 FreePool (Private
->DhcpPacketBuffer
);
2255 Private
->DhcpPacketBuffer
= NULL
;
2260 Private
->ReceiveBuffers
= AllocatePool (sizeof (DHCP_RECEIVE_BUFFER
) * (MAX_OFFERS
));
2261 if (Private
->ReceiveBuffers
== NULL
) {
2262 FreePool (Private
->TransmitBuffer
);
2263 FreePool (Private
->DhcpPacketBuffer
);
2264 Private
->DhcpPacketBuffer
= NULL
;
2265 Private
->TransmitBuffer
= NULL
;
2273 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2277 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2278 IN BOOLEAN SortOffers
2281 Routine description:
2282 standard DHCP Discover/Offer/Request/Ack session
2283 broadcast DHCPDISCOVER
2285 broadcast DHCPREQUEST
2290 This := Pointer to PxeBc interface
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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_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 ((EFI_D_INFO
, "\nBcDhcp() Enter. "));
2332 PxebcMode
= Private
->EfiBc
.Mode
;
2334 if (!GetMem (Private
)) {
2335 DEBUG ((EFI_D_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 ((EFI_D_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 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2439 PXE_BASECODE_DEVICE
*Private
,
2442 IN UINT16
*LayerPtr
,
2444 EFI_IP_ADDRESS
*DestPtr
,
2445 PXE_SERVER_LISTS
*ServerListPtr
2448 Routine description:
2449 This function tries to complete the PXE Bootserver and/or boot image
2450 discovery sequence. When this command completes successfully, the
2451 PXEdiscover and PXEreply fields in the BC instance data structure are
2452 updated. If the Info pointer is set to NULL, the discovery information
2453 in the DHCPack and ProxyOffer packets must be valid and will be used.
2454 If Info is not set to NULL, the discovery methods in the Info field
2455 must be set and will be used. When discovering any layer number other
2456 than zero (the credential flag does not count), only unicast discovery
2460 Private := Pointer to PxeBc interface
2471 EFI_PXE_BASE_CODE_UDP_PORT ClientPort
;
2472 EFI_PXE_BASE_CODE_UDP_PORT ServerPort
;
2473 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2474 EFI_STATUS StatCode
;
2475 EFI_EVENT TimeoutEvent
;
2478 PxebcMode
= Private
->EfiBc
.Mode
;
2480 if (DestPtr
->Addr
[0] == 0) {
2481 DEBUG ((EFI_D_WARN
, "\nDoDiscover() !DestPtr->Addr[0]"));
2482 return EFI_INVALID_PARAMETER
;
2485 // seed random number with hardware address
2487 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2489 if (DestPtr
->Addr
[0] == BroadcastIP
.Addr
[0]) {
2490 ClientPort
= DHCPClientPort
;
2491 ServerPort
= DhcpServerPort
;
2493 ClientPort
= PSEUDO_DHCP_CLIENT_PORT
;
2494 ServerPort
= PseudoDhcpServerPort
;
2498 *LayerPtr
|= PXE_BOOT_LAYER_CREDENTIAL_FLAG
;
2500 *LayerPtr
&= PXE_BOOT_LAYER_MASK
;
2503 for (Private
->Timeout
= 1;
2504 Private
->Timeout
< 5;
2505 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Private
->Timeout
2507 InitDhcpv4TxBuf (Private
);
2509 // initialize DHCP message structure
2511 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2512 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2514 &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2515 &PxebcMode
->StationIp
,
2516 sizeof DHCPV4_TRANSMIT_BUFFER
.ciaddr
2519 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
2520 DISCOVERoptions
.Header
.OpCode
= OP_VENDOR_SPECIFIC
;
2521 DISCOVERoptions
.BootItem
.Header
.OpCode
= VEND_PXE_BOOT_ITEM
;
2522 DISCOVERoptions
.BootItem
.Header
.Length
= DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM
);
2523 DISCOVERoptions
.BootItem
.Type
= HTONS (Type
);
2524 DISCOVERoptions
.BootItem
.Layer
= HTONS (*LayerPtr
);
2527 EFI_BIS_PROTOCOL
*BisPtr
;
2528 BIS_APPLICATION_HANDLE BisAppHandle
;
2529 EFI_BIS_DATA
*BisDataSigInfo
;
2530 EFI_BIS_SIGNATURE_INFO
*BisSigInfo
;
2534 BisPtr
= PxebcBisStart (
2540 if (BisPtr
== NULL
) {
2542 // %%TBD - In order to get here, BIS must have
2543 // been present when PXEBC.Start() was called.
2544 // BIS had to be shutdown/removed/damaged
2545 // before PXEBC.Discover() was called.
2546 // Do we need to document a specific error
2549 return EFI_OUT_OF_RESOURCES
;
2552 // Compute number of credential types.
2554 Index2
= BisDataSigInfo
->Length
/ sizeof (EFI_BIS_SIGNATURE_INFO
);
2556 DISCREDoptions
.Header
.OpCode
= VEND_PXE_CREDENTIAL_TYPES
;
2558 DISCREDoptions
.Header
.Length
= (UINT8
) (Index2
* sizeof (PXE_CREDENTIAL
));
2560 OpLen
= (UINT8
) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
) + sizeof (DHCPV4_OP_HEADER
) + DISCREDoptions
.Header
.Length
);
2562 BisSigInfo
= (EFI_BIS_SIGNATURE_INFO
*) BisDataSigInfo
->Data
;
2564 for (Index
= 0; Index
< Index2
; ++Index
) {
2567 CopyMem (&x
, &BisSigInfo
[Index
], sizeof x
);
2569 CopyMem (&DISCREDoptions
.Credentials
[Index
], &x
, sizeof x
);
2572 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
2574 OpLen
= DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
);
2577 DISCOVERoptions
.Header
.Length
= OpLen
;
2579 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
- 1] = OP_END
;
2580 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
] = OP_END
;
2582 StatCode
= DoUdpWrite (
2586 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2590 if (StatCode
!= EFI_SUCCESS
) {
2596 StatCode
= gBS
->CreateEvent (
2604 if (EFI_ERROR (StatCode
)) {
2608 StatCode
= gBS
->SetTimer (
2611 Private
->Timeout
* 10000000 + 1000000
2614 if (EFI_ERROR (StatCode
)) {
2615 gBS
->CloseEvent (TimeoutEvent
);
2622 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
2626 RxBufPtr
= UseBis
? &PXE_BIS_BUFFER
: &PXE_ACK_BUFFER
;
2627 ZeroMem (&Private
->ServerIp
, sizeof (EFI_IP_ADDRESS
));
2633 (EFI_IP_ADDRESS
*) &Private
->ServerIp
,
2635 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2643 // check type of response - need PXEClient DHCPACK of proper type with bootfile
2645 if (!(RxBufPtr
->OpAdds
.Status
& PXE_TYPE
) ||
2646 (UseBis
&& (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
)) ||
2647 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] ||
2648 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1] ||
2649 !InServerList((EFI_IP_ADDRESS
*)&((DHCPV4_OP_SERVER_IP
*)RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
-1])->Ip
, ServerListPtr
)) {
2654 TmpType
= TmpLayer
= 0;
2656 if (RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
2657 TmpType
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Type
);
2659 if (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
) {
2660 TmpLayer
= (UINT16
) (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
>> 8);
2662 TmpLayer
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
);
2666 if (TmpType
!= Type
) {
2671 if (!RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]) {
2675 if (!VerifyCredentialOption (
2676 (UINT8
*) &DISCREDoptions
.Header
,
2677 (UINT8
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]
2683 *LayerPtr
= TmpLayer
;
2687 &PxebcMode
->PxeBisReply
,
2688 &RxBufPtr
->u
.Dhcpv4
,
2689 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2692 PxebcMode
->PxeBisReplyReceived
= TRUE
;
2694 StatCode
= DoDiscover (
2696 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2704 gBS
->CloseEvent (TimeoutEvent
);
2708 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= TRUE
;
2711 &PxebcMode
->PxeDiscover
,
2712 &*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2713 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
)
2717 &PxebcMode
->PxeReply
,
2718 &*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
,
2719 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
)
2722 AddRouters (Private
, RxBufPtr
);
2724 gBS
->CloseEvent (TimeoutEvent
);
2728 gBS
->CloseEvent (TimeoutEvent
);
2736 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2740 PXE_BASECODE_DEVICE
*Private
,
2742 IN UINT16
*LayerPtr
,
2744 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*DiscoverInfoPtr
,
2745 PXE_SERVER_LISTS
*McastServerListPtr
,
2746 PXE_SERVER_LISTS
*ServerListPtr
2749 Routine Description:
2752 Private := Pointer to PxeBc interface
2757 McastServerListPtr :=
2763 EFI_IP_ADDRESS DestIp
;
2764 EFI_STATUS StatCode
;
2766 DEBUG ((EFI_D_INFO
, "\nDiscover() Type=%d Layer=%d ", Type
, *LayerPtr
));
2769 DEBUG ((EFI_D_INFO
, "BIS "));
2772 // get dest IP addr - mcast, bcast, or unicast
2774 if (DiscoverInfoPtr
->UseMCast
) {
2775 DestIp
.v4
= DiscoverInfoPtr
->ServerMCastIp
.v4
;
2779 "\nDiscover() MCast %d.%d.%d.%d ",
2786 if ((StatCode
= DoDiscover (
2788 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2794 )) != EFI_TIMEOUT
) {
2797 "\nDiscover() status == %r (%Xh)",
2806 if (DiscoverInfoPtr
->UseBCast
) {
2807 DEBUG ((EFI_D_INFO
, "\nDiscver() BCast "));
2809 if ((StatCode
= DoDiscover (
2811 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2817 )) != EFI_TIMEOUT
) {
2819 DEBUG ((EFI_D_WARN
, "\nDiscover() status == %r (%Xh)", StatCode
, StatCode
));
2825 if (DiscoverInfoPtr
->UseUCast
) {
2830 "\nDiscover() UCast IP#=%d ",
2831 ServerListPtr
->Ipv4List
.IpCount
)
2834 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2835 CopyMem (&DestIp
, &ServerListPtr
->Ipv4List
.IpList
[Index
], 4);
2839 "\nDiscover() UCast %d.%d.%d.%d ",
2846 if ((StatCode
= DoDiscover (
2848 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2854 )) != EFI_TIMEOUT
) {
2857 "\nDiscover() status == %r (%Xh)",
2867 DEBUG ((EFI_D_WARN
, "\nDiscover() TIMEOUT"));
2872 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2879 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
2881 IN UINT16
*LayerPtr
,
2883 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
* DiscoverInfoPtr OPTIONAL
2886 Routine description:
2898 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
2899 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2900 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
2901 PXE_SERVER_LISTS DefaultSrvList
;
2902 PXE_SERVER_LISTS
*ServerListPtr
;
2903 PXE_SERVER_LISTS
*McastServerListPtr
;
2907 BOOLEAN AcquiredSrvList
;
2908 EFI_STATUS StatCode
;
2909 PXE_BASECODE_DEVICE
*Private
;
2912 // Lock the instance data and make sure started
2914 StatCode
= EFI_SUCCESS
;
2917 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
2918 return EFI_INVALID_PARAMETER
;
2921 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2923 if (Private
== NULL
) {
2924 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2925 return EFI_INVALID_PARAMETER
;
2928 EfiAcquireLock (&Private
->Lock
);
2930 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2931 DEBUG ((EFI_D_ERROR
, "BC was not started."));
2932 EfiReleaseLock (&Private
->Lock
);
2933 return EFI_NOT_STARTED
;
2936 ServerListPtr
= NULL
;
2937 McastServerListPtr
= NULL
;
2938 AcquiredSrvList
= FALSE
;
2940 PxebcMode
= Private
->EfiBc
.Mode
;
2942 if (!GetMem (Private
)) {
2943 EfiReleaseLock (&Private
->Lock
);
2944 return EFI_OUT_OF_RESOURCES
;
2948 if (!PxebcMode
->BisSupported
) {
2949 EfiReleaseLock (&Private
->Lock
);
2950 return EFI_INVALID_PARAMETER
;
2954 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
2956 if (Private
->TotalSeconds
== 0) {
2958 // put in seconds field of DHCP send packets
2960 Private
->TotalSeconds
= 4;
2963 ZeroMem (&DefaultInfo
, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO
));
2966 // if layer number not zero, use previous discover
2968 if (*LayerPtr
!= 0) {
2969 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0"));
2971 if (DiscoverInfoPtr
!= NULL
) {
2972 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n"));
2974 EfiReleaseLock (&Private
->Lock
);
2975 return EFI_INVALID_PARAMETER
;
2978 if (!PxebcMode
->PxeDiscoverValid
) {
2979 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n"));
2981 EfiReleaseLock (&Private
->Lock
);
2982 return EFI_INVALID_PARAMETER
;
2985 if (!PxebcMode
->PxeReplyReceived
) {
2986 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n"));
2988 EfiReleaseLock (&Private
->Lock
);
2989 return EFI_INVALID_PARAMETER
;
2992 if (UseBis
&& !PxebcMode
->PxeBisReplyReceived
) {
2993 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n"));
2995 EfiReleaseLock (&Private
->Lock
);
2996 return EFI_INVALID_PARAMETER
;
2999 DefaultInfo
.UseUCast
= TRUE
;
3000 DiscoverInfoPtr
= &DefaultInfo
;
3002 DefaultSrvList
.Ipv4List
.IpCount
= 1;
3003 CopyMem (&DefaultSrvList
.Ipv4List
.IpList
[0], &Private
->ServerIp
, 4);
3005 ServerListPtr
= &DefaultSrvList
;
3008 // layer is zero - see if info is supplied or if we need to use info from a cached offer
3010 else if (!DiscoverInfoPtr
) {
3012 // not supplied - generate it
3013 // make sure that there is cached, appropriate information
3014 // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail
3016 DhcpRxBuf
= (PxebcMode
->ProxyOfferReceived
) ? &PXE_OFFER_BUFFER
: &DHCPV4_ACK_BUFFER
;
3018 if (!PxebcMode
->DhcpAckReceived
|| !(DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
)) {
3019 DEBUG ((EFI_D_WARN
, "\nBcDiscover() !ack && !proxy"));
3020 EfiReleaseLock (&Private
->Lock
);
3021 return EFI_INVALID_PARAMETER
;
3024 DiscoverInfoPtr
= &DefaultInfo
;
3026 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
3029 // if multicast enabled, need multicast address
3031 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
)) {
3032 DefaultInfo
.UseMCast
= TRUE
;
3035 ((EFI_IPv4_ADDRESS
*) &DefaultInfo
.ServerMCastIp
),
3036 &((DHCPV4_OP_IP_ADDRESS
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1])->Ip
,
3037 sizeof (EFI_IPv4_ADDRESS
)
3041 DefaultInfo
.UseBCast
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_BCAST
) == 0);
3043 DefaultInfo
.MustUseList
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) != 0);
3045 DefaultInfo
.UseUCast
= (BOOLEAN
)
3047 (DefaultInfo
.MustUseList
) ||
3048 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
3051 if ((DefaultInfo
.UseUCast
| DefaultInfo
.MustUseList
) && !ExtractBootServerList (
3053 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1],
3056 DEBUG ((EFI_D_WARN
, "\nBcDiscover() type not in list"));
3057 EfiReleaseLock (&Private
->Lock
);
3058 return EFI_INVALID_PARAMETER
;
3062 // Info supplied - make SrvList if required
3063 // if we use ucast discovery or must use list, there better be one
3065 else if (DiscoverInfoPtr
->UseUCast
|| DiscoverInfoPtr
->MustUseList
) {
3067 // there better be a list
3069 if (DiscoverInfoPtr
->IpCnt
== 0) {
3070 DEBUG ((EFI_D_WARN
, "\nBcDiscover() no bootserver list"));
3071 EfiReleaseLock (&Private
->Lock
);
3072 return EFI_INVALID_PARAMETER
;
3077 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3078 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3079 if (DiscoverInfoPtr
->SrvList
[Index
].AcceptAnyResponse
) {
3081 DEBUG ((EFI_D_WARN
, "\nBcDiscover() accept any?"));
3082 EfiReleaseLock (&Private
->Lock
);
3083 return EFI_INVALID_PARAMETER
;
3086 DefaultSrvList
.Ipv4List
.IpCount
= 0;
3087 ServerListPtr
= &DefaultSrvList
;
3097 DEBUG ((EFI_D_WARN
, "\nBcDiscover() !Index2?"));
3098 EfiReleaseLock (&Private
->Lock
);
3099 return EFI_INVALID_PARAMETER
;
3102 if (ServerListPtr
== NULL
) {
3103 ServerListPtr
= AllocatePool (
3104 sizeof (PXEV4_SERVER_LIST
) + (Index2
- 1) * sizeof (EFI_IPv4_ADDRESS
)
3107 if (ServerListPtr
== NULL
) {
3108 EfiReleaseLock (&Private
->Lock
);
3109 return EFI_OUT_OF_RESOURCES
;
3112 // build an array of IP addresses from the server list
3114 AcquiredSrvList
= TRUE
;
3115 ServerListPtr
->Ipv4List
.IpCount
= (UINT8
) Index2
;
3117 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3118 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3120 &ServerListPtr
->Ipv4List
.IpList
[Index2
++],
3121 &DiscoverInfoPtr
->SrvList
[Index
].IpAddr
.v4
,
3122 sizeof ServerListPtr
->Ipv4List
.IpList
[0]
3129 if (DiscoverInfoPtr
->MustUseList
) {
3130 McastServerListPtr
= ServerListPtr
;
3133 if (!(DiscoverInfoPtr
->UseMCast
|| DiscoverInfoPtr
->UseBCast
|| DiscoverInfoPtr
->UseUCast
)) {
3134 DEBUG ((EFI_D_WARN
, "\nBcDiscover() Nothing to use!\n"));
3136 EfiReleaseLock (&Private
->Lock
);
3137 return EFI_INVALID_PARAMETER
;
3140 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= PxebcMode
->PxeBisReplyReceived
= FALSE
;
3142 StatCode
= Discover (
3152 if (AcquiredSrvList
) {
3153 FreePool (ServerListPtr
);
3159 // Unlock the instance data
3163 "\nBcDiscover() status == %r (%Xh)\n",
3168 EfiReleaseLock (&Private
->Lock
);
3172 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3176 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
3177 BOOLEAN
*NewDhcpDiscoverValid
, OPTIONAL
3178 BOOLEAN
*NewDhcpAckReceived
, OPTIONAL
3179 BOOLEAN
*NewProxyOfferReceived
, OPTIONAL
3180 BOOLEAN
*NewPxeDiscoverValid
, OPTIONAL
3181 BOOLEAN
*NewPxeReplyReceived
, OPTIONAL
3182 BOOLEAN
*NewPxeBisReplyReceived
, OPTIONAL
3183 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
3184 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
3185 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
3186 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
3187 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
3188 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
3191 Routine description:
3198 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
3199 PXE_BASECODE_DEVICE
*Private
;
3202 // Lock the instance data and make sure started
3206 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
3207 return EFI_INVALID_PARAMETER
;
3210 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
3212 if (Private
== NULL
) {
3213 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
3214 return EFI_INVALID_PARAMETER
;
3217 EfiAcquireLock (&Private
->Lock
);
3219 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
3220 DEBUG ((EFI_D_ERROR
, "BC was not started."));
3221 EfiReleaseLock (&Private
->Lock
);
3222 return EFI_NOT_STARTED
;
3225 PxebcMode
= Private
->EfiBc
.Mode
;
3227 if (Private
->DhcpPacketBuffer
== NULL
) {
3228 Private
->DhcpPacketBuffer
= AllocatePool (sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1));
3229 if (Private
->DhcpPacketBuffer
== NULL
) {
3230 EfiReleaseLock (&Private
->Lock
);
3231 return EFI_OUT_OF_RESOURCES
;
3240 Private
->FileSize
= 0;
3241 if (NewDhcpDiscoverValid
!= NULL
) {
3242 PxebcMode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
3245 if (NewDhcpAckReceived
!= NULL
) {
3246 PxebcMode
->DhcpAckReceived
= *NewDhcpAckReceived
;
3249 if (NewProxyOfferReceived
!= NULL
) {
3250 PxebcMode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
3253 if (NewPxeDiscoverValid
!= NULL
) {
3254 PxebcMode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
3257 if (NewPxeReplyReceived
!= NULL
) {
3258 PxebcMode
->PxeReplyReceived
= *NewPxeReplyReceived
;
3261 if (NewPxeBisReplyReceived
!= NULL
) {
3262 PxebcMode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
3265 if (NewDhcpDiscover
!= NULL
) {
3267 &PxebcMode
->DhcpDiscover
,
3269 sizeof *NewDhcpDiscover
3273 if (NewDhcpAck
!= NULL
) {
3274 CopyParse (Private
, &PxebcMode
->DhcpAck
, NewDhcpAck
, DHCPV4_ACK_INDEX
);
3277 if (NewProxyOffer
!= NULL
) {
3278 CopyParse (Private
, &PxebcMode
->ProxyOffer
, NewProxyOffer
, PXE_OFFER_INDEX
);
3281 if (NewPxeDiscover
!= NULL
) {
3283 &PxebcMode
->PxeDiscover
,
3285 sizeof *NewPxeDiscover
3289 if (NewPxeReply
!= NULL
) {
3290 CopyParse (Private
, &PxebcMode
->PxeReply
, NewPxeReply
, PXE_ACK_INDEX
);
3293 if (NewPxeBisReply
!= NULL
) {
3294 CopyParse (Private
, &PxebcMode
->PxeBisReply
, NewPxeBisReply
, PXE_BIS_INDEX
);
3297 // Unlock the instance data
3299 EfiReleaseLock (&Private
->Lock
);
3303 /* eof - pxe_bc_dhcp.c */