3 Copyright (c) 2006, 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 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
403 PxeBcLibGetSmbiosString (
404 IN SMBIOS_STRUCTURE_POINTER
*Smbios
,
405 IN UINT16 StringNumber
409 Return SMBIOS string given the string number.
412 Smbios - Pointer to SMBIOS structure
413 StringNumber - String number to return. 0 is used to skip all strings and
414 point to the next SMBIOS structure.
417 Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == 0
424 // Skip over formatted section
426 String
= (CHAR8
*) (Smbios
->Raw
+ Smbios
->Hdr
->Length
);
429 // Look through unformated section
431 for (Index
= 1; Index
<= StringNumber
|| StringNumber
== 0; Index
++) {
432 if (StringNumber
== Index
) {
438 for (; *String
!= 0; String
++)
444 // If double NULL then we are done.
445 // Return pointer to next structure in Smbios.
446 // if you pass in a 0 you will always get here
448 Smbios
->Raw
= (UINT8
*)++String
;
457 PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
458 IN EFI_GUID
*SystemGuid
,
459 OUT CHAR8
**SystemSerialNumber
464 This function gets system guid and serial number from the smbios table
467 SystemGuid - The pointer of returned system guid
468 SystemSerialNumber - The pointer of returned system serial number
471 EFI_SUCCESS - Successfully get the system guid and system serial number
472 EFI_NOT_FOUND - Not find the SMBIOS table
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
623 Ip4AddRouter (Private
, &RxBufPtr
->u
.Dhcpv4
.giaddr
);
627 (DHCPV4_OP_IP_LIST
*) RxBufPtr
->OpAdds
.PktOptAdds
[OP_ROUTER_LIST_IX
- 1]
631 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
635 PXE_BASECODE_DEVICE
*Private
,
636 EFI_IP_ADDRESS
*ServerIpPtr
,
637 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
638 EFI_IP_ADDRESS
*ClientIpPtr
,
639 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
644 Len
= sizeof DHCPV4_TRANSMIT_BUFFER
;
648 EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT
,
657 Private
->TransmitBuffer
661 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
664 // initialize the DHCP structure
673 PXE_BASECODE_DEVICE
*Private
678 CHAR8
*SystemSerialNumber
;
679 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
681 PxebcMode
= Private
->EfiBc
.Mode
;
683 ZeroMem (&DHCPV4_TRANSMIT_BUFFER
, sizeof (DHCPV4_STRUCT
));
684 DHCPV4_TRANSMIT_BUFFER
.op
= BOOTP_REQUEST
;
685 DHCPV4_TRANSMIT_BUFFER
.htype
= Private
->SimpleNetwork
->Mode
->IfType
;
686 DHCPV4_TRANSMIT_BUFFER
.flags
= HTONS (DHCP_BROADCAST_FLAG
);
687 CopyMem (&DHCPV4_OPTIONS_BUFFER
, (VOID
*) &DHCPOpStart
, sizeof (DHCPOpStart
));
690 // default to hardware address
692 HwAddrLen
= Private
->SimpleNetwork
->Mode
->HwAddressSize
;
694 if (HwAddrLen
> sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
) {
695 HwAddrLen
= sizeof DHCPV4_TRANSMIT_BUFFER
.chaddr
;
698 String
= (UINT8
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
;
700 if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (
701 (EFI_GUID
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
,
704 if (PxebcMode
->SendGUID
) {
705 HwAddrLen
= sizeof (EFI_GUID
);
706 String
= (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
;
710 // GUID not yet set - send all 0xff's to show programable (via SetVariable)
711 // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff);
712 // GUID not yet set - send all 0's to show not programable
714 ZeroMem (DHCPV4_OPTIONS_BUFFER
.DhcpPlatformId
.Guid
, sizeof (EFI_GUID
));
717 DHCPV4_TRANSMIT_BUFFER
.hlen
= (UINT8
) HwAddrLen
;
718 CopyMem (DHCPV4_TRANSMIT_BUFFER
.chaddr
, String
, HwAddrLen
);
722 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
,
723 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.ArchitectureType
726 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.Type
= Private
->NiiPtr
->Type
;
727 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
= Private
->NiiPtr
->MajorVer
;
728 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
= Private
->NiiPtr
->MinorVer
;
730 *(C4Str
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.InterfaceName
= *(C4Str
*) Private
->NiiPtr
->StringId
;
733 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MajorVersion
,
734 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
,
735 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMajor
739 DHCPV4_OPTIONS_BUFFER
.DhcpNetworkInterface
.MinorVersion
,
740 (UINT8
*) DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
,
741 sizeof DHCPV4_OPTIONS_BUFFER
.DhcpClassIdentifier
.Data
.UndiMinor
745 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
749 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
762 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
775 LocalPtr
.BytePtr
= ptr
;
776 if (Op
<= MAX_OUR_PXE_OPT
) {
777 Index
= ourPXEopts
[Op
- 1];
779 RxBufPtr
->OpAdds
.PxeOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
780 status
|= 1 << Index
;
781 if (Index
== VEND_PXE_BOOT_ITEM
&& LocalPtr
.BootItem
->Header
.Length
== 3) {
782 RxBufPtr
->OpAdds
.Status
|= USE_THREE_BYTE
;
793 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
797 DHCP_RECEIVE_BUFFER
*RxBufPtr
,
807 for (EndPtr
= ptr
+ Len
; ptr
< EndPtr
; ptr
+= Len
+ 2) {
820 LocalPtr
.BytePtr
= ptr
;
821 if (Op
<= MAX_OUR_OPT
) {
822 Index
= OurDhcpOptions
[Op
- 1];
824 RxBufPtr
->OpAdds
.PktOptAdds
[Index
- 1] = LocalPtr
.OpPtr
;
825 if (Index
== OP_VENDOR_SPECIFIC_IX
) {
827 status
= DecodePxeOptions (
829 (UINT8
*) LocalPtr
.VendorOptions
->VendorOptions
,
830 LocalPtr
.VendorOptions
->Header
.Length
833 RxBufPtr
->OpAdds
.Status
|= PXE_TYPE
;
835 // check for all the MTFTP info options present - any missing is a nogo
837 if ((status
& WfM11a_OPTS
) == WfM11a_OPTS
) {
838 RxBufPtr
->OpAdds
.Status
|= WfM11a_TYPE
;
841 if (status
& DISCOVER_OPTS
) {
842 RxBufPtr
->OpAdds
.Status
|= DISCOVER_TYPE
;
845 if (status
& CREDENTIALS_OPT
) {
846 RxBufPtr
->OpAdds
.Status
|= CREDENTIALS_TYPE
;
857 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
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 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
963 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
968 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
972 // if a DHCP type, must be DHCPOFFER and must have server id
977 (LocalPtr
.MessageType
->Type
== DHCPACK
) &&
978 DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]
982 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
985 // if a discover type packet, make sure all required fields are present
989 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
992 PXE_OP_SERVER_LIST
*BootServerOpPtr
;
995 if ((DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) == 0) {
999 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
1001 if (LocalPtr
.OpPtr
== NULL
) {
1002 LocalPtr
.OpPtr
= (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
1003 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultDisCtl
;
1006 // make sure all required fields are here
1007 // if mucticast enabled, need multicast address
1009 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
) &&
1010 (!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
))
1014 // missing required field
1018 // if a list, it better be good
1020 BootServerOpPtr
= (PXE_OP_SERVER_LIST
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1];
1022 if (BootServerOpPtr
!= NULL
) {
1023 PXE_SERVER_LIST
*BootServerListPtr
;
1025 INTN ServerEntryLen
;
1027 BootServerListPtr
= BootServerOpPtr
->ServerList
;
1028 ServerListLen
= BootServerOpPtr
->Header
.Length
;
1031 EFI_IPv4_ADDRESS
*IpListPtr
;
1034 IpCnt
= BootServerListPtr
->u
.Ipv4List
.IpCount
;
1036 ServerEntryLen
= sizeof (PXEV4_SERVER_LIST
) + 2 + (IpCnt
- 1) * sizeof (EFI_IPv4_ADDRESS
);
1038 if (ServerListLen
< ServerEntryLen
) {
1040 // missing required field
1045 IpListPtr
= BootServerListPtr
->u
.Ipv4List
.IpList
;
1048 if (IS_MULTICAST (IpListPtr
)) {
1050 // missing required field
1058 BootServerListPtr
= (PXE_SERVER_LIST
*) IpListPtr
;
1059 } while (ServerListLen
-= ServerEntryLen
);
1062 // else there must be a list if use list enabled or multicast and
1063 // broadcast disabled
1065 else if ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) ||
1066 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
1069 // missing required field
1074 // if not USE_BOOTFILE or no bootfile given, must have menu stuff
1076 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& USE_BOOTFILE
) ||
1077 !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1081 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_MENU_IX
- 1];
1083 if (LocalPtr
.OpPtr
== NULL
|| !DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_PROMPT_IX
- 1]) {
1085 // missing required field
1090 // make sure menu valid
1092 MenuLth
= LocalPtr
.BootMenu
->Header
.Length
;
1093 LocalPtr
.BootMenuItem
= LocalPtr
.BootMenu
->MenuItem
;
1098 MenuItemLen
= LocalPtr
.BootMenuItem
->DataLen
;
1100 if (MenuItemLen
== 0) {
1102 // missing required field
1107 MenuItemLen
+= sizeof (*LocalPtr
.BootMenuItem
) - sizeof (LocalPtr
.BootMenuItem
->Data
);
1109 MenuLth
-= MenuItemLen
;
1110 LocalPtr
.BytePtr
+= MenuItemLen
;
1111 } while (MenuLth
> 0);
1115 // missing required field
1121 if (!DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
1122 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1] = (DHCPV4_OP_STRUCT
*) &DefaultBootItem
;
1128 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1131 DHCP_RECEIVE_BUFFER
*RxBufPtr
1134 return (BOOLEAN
) (DHCPOfferAckEdit (RxBufPtr
) ? AckEdit (RxBufPtr
) : FALSE
);
1137 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1144 PXE_BASECODE_DEVICE
*Private
,
1145 BOOLEAN (*ExtraEdit
)(DHCP_RECEIVE_BUFFER
*DhcpRxBuf
),
1146 UINT16 OpFlags
, // for Udp read
1147 EFI_IP_ADDRESS
*ServerIpPtr
,
1148 EFI_PXE_BASE_CODE_UDP_PORT
*ServerPortPtr
,
1149 EFI_IP_ADDRESS
*ClientIpPtr
,
1150 EFI_PXE_BASE_CODE_UDP_PORT
*ClientPortPtr
,
1151 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
,
1152 EFI_EVENT TimeoutEvent
1155 Routine description:
1156 Wait for an OFFER/ACK packet.
1159 Private := Pointer to PxeBc interface
1160 ExtraEdit := Pointer to extra option checking function
1161 OpFlags := UdpRead() option flags
1172 EFI_IP_ADDRESS ServerIp
;
1173 EFI_STATUS StatCode
;
1178 // Wait until we get a UDP packet.
1180 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1181 RxBufLen
= sizeof RxBuf
[0].u
.ReceiveBuffer
;
1183 if ((StatCode
= UdpRead (
1192 (UINTN
*) &RxBufLen
,
1193 &DhcpRxBuf
->u
.Dhcpv4
,
1195 )) != EFI_SUCCESS
) {
1196 if (StatCode
== EFI_TIMEOUT
) {
1197 StatCode
= EFI_NO_RESPONSE
;
1203 // got a packet - see if a good offer
1205 if (DhcpRxBuf
->u
.Dhcpv4
.op
!= BOOTP_REPLY
) {
1209 if (DhcpRxBuf
->u
.Dhcpv4
.xid
!= DHCPV4_TRANSMIT_BUFFER
.xid
) {
1213 if (*(UINT32
*) DHCPV4_TRANSMIT_BUFFER
.options
!= * (UINT32
*) DhcpRxBuf
->u
.Dhcpv4
.options
) {
1217 if (*(UINT8
*) &DhcpRxBuf
->u
.Dhcpv4
.yiaddr
> 223) {
1222 DhcpRxBuf
->u
.Dhcpv4
.chaddr
,
1223 DHCPV4_TRANSMIT_BUFFER
.chaddr
,
1224 sizeof DhcpRxBuf
->u
.Dhcpv4
.chaddr
1232 Parse (DhcpRxBuf
, RxBufLen
);
1234 if (!(*ExtraEdit
) (DhcpRxBuf
)) {
1238 // Good DHCP packet.
1240 StatCode
= EFI_SUCCESS
;
1247 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1254 PXE_BASECODE_DEVICE
*Private
1257 EFI_IP_ADDRESS ClientIp
;
1258 EFI_IP_ADDRESS ServerIp
;
1259 EFI_STATUS StatCode
;
1260 EFI_EVENT TimeoutEvent
;
1267 ZeroMem (&ServerIp
, sizeof (EFI_IP_ADDRESS
));
1270 for (Index
= 0; Index
< (sizeof Private
->ServerCount
) / sizeof Private
->ServerCount
[0]; ++Index
) {
1271 Private
->ServerCount
[Index
] = 0;
1272 Private
->GotProxy
[Index
] = 0;
1275 Private
->GotBootp
= 0;
1277 // these we throw away
1279 Private
->GotProxy
[DHCP_ONLY_IX
] = 1;
1280 StatCode
= gBS
->CreateEvent (
1288 if (EFI_ERROR (StatCode
)) {
1292 StatCode
= gBS
->SetTimer (
1295 Private
->Timeout
* 10000000 + 1000000
1298 if (EFI_ERROR (StatCode
)) {
1299 gBS
->CloseEvent (TimeoutEvent
);
1306 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1309 DhcpRxBuf
= &RxBuf
[NumOffers
];
1312 StatCode
= GetOfferAck (
1315 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
|
1316 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP
|
1317 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1330 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_MESSAGE_TYPE_IX
- 1];
1333 // check type of offer
1335 if (LocalPtr
.OpPtr
== NULL
) {
1337 // bootp - we only need one and make sure has bootfile
1339 if (Private
->GotBootp
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1343 Private
->GotBootp
= (UINT8
) (NumOffers
+ 1);
1346 // if a DHCP type, must be DHCPOFFER and must have server id
1348 else if (LocalPtr
.MessageType
->Type
!= DHCPOFFER
|| !DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1]) {
1354 // get type - PXE10, WfM11a, or BINL
1356 if (DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
) {
1358 } else if (DhcpRxBuf
->OpAdds
.Status
& WfM11a_TYPE
) {
1360 // WfM - make sure it has a bootfile
1362 if (!DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]) {
1368 TypeIx
= (DhcpRxBuf
->OpAdds
.Status
& PXE_TYPE
) ? BINL_IX
: DHCP_ONLY_IX
;
1371 // check DHCP or proxy
1373 if (DhcpRxBuf
->u
.Dhcpv4
.yiaddr
== 0) {
1375 // proxy - only need one of each type if not BINL
1376 // and must have at least PXE_TYPE
1378 if (TypeIx
== BINL_IX
) {
1379 Private
->BinlProxies
[Private
->GotProxy
[BINL_IX
]++] = (UINT8
) NumOffers
;
1380 } else if (Private
->GotProxy
[TypeIx
]) {
1383 Private
->GotProxy
[TypeIx
] = (UINT8
) (NumOffers
+ 1);
1386 Private
->OfferCount
[TypeIx
][Private
->ServerCount
[TypeIx
]++] = (UINT8
) NumOffers
;
1390 if (++NumOffers
== MAX_OFFERS
) {
1395 gBS
->CloseEvent (TimeoutEvent
);
1396 Private
->NumOffersReceived
= NumOffers
;
1398 return (Private
->NumOffersReceived
) ? EFI_SUCCESS
: EFI_NO_RESPONSE
;
1401 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1409 PXE_BASECODE_DEVICE
*Private
1412 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1415 PxebcMode
= Private
->EfiBc
.Mode
;
1416 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1418 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1419 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1421 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opdeclinestr
),
1422 sizeof (DHCPOpStart
) - sizeof (struct opdeclinestr
),
1425 DHCPDECLINEoptions
.DhcpMessageType
.Type
= DHCPDECLINE
;
1426 CopyMem (&DHCPDECLINEoptions
.OpDeclineEnd
, &DHCP_REQ_OPTIONS
, sizeof (struct requestopendstr
));
1427 // DHCPDECLINEoptions.OpDeclineEnd = DHCP_REQ_OPTIONS;
1430 EFI_IP_ADDRESS TmpIp
;
1432 CopyMem (&TmpIp
, &DHCP_REQ_OPTIONS
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1438 &PxebcMode
->StationIp
,
1443 InitDhcpv4TxBuf (Private
);
1444 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1445 Private
->GoodStationIp
= FALSE
;
1448 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1456 PXE_BASECODE_DEVICE
*Private
1459 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
1461 DHCPV4_OP_SERVER_IP
*Point
;
1463 PxebcMode
= Private
->EfiBc
.Mode
;
1464 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1465 DHCPV4_TRANSMIT_BUFFER
.secs
= 0;
1468 DHCPV4_TRANSMIT_BUFFER
.options
+ sizeof (struct opreleasestr
),
1469 sizeof (DHCPOpStart
) - sizeof (struct opreleasestr
),
1473 DHCPRELEASEoptions
.DhcpMessageType
.Type
= DHCPRELEASE
;
1474 Point
= (DHCPV4_OP_SERVER_IP
*) DHCPV4_ACK_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1];
1476 &DHCPRELEASEoptions
.DhcServerIpPtr
,
1478 sizeof DHCPRELEASEoptions
.DhcServerIpPtr
1481 DHCPRELEASEoptions
.End
[0] = OP_END
;
1484 EFI_IP_ADDRESS TmpIp
;
1486 CopyMem (&TmpIp
, &DHCPRELEASEoptions
.DhcServerIpPtr
.Ip
, sizeof TmpIp
);
1492 &PxebcMode
->StationIp
,
1497 InitDhcpv4TxBuf (Private
);
1499 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1500 Private
->GoodStationIp
= FALSE
;
1504 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1508 PXE_BASECODE_DEVICE
*Private
,
1509 EFI_IP_ADDRESS
*ServerIpPtr
1512 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1513 EFI_STATUS StatCode
;
1514 EFI_EVENT TimeoutEvent
;
1519 StatCode
= gBS
->CreateEvent (
1527 if (EFI_ERROR (StatCode
)) {
1531 StatCode
= gBS
->SetTimer (
1534 Private
->Timeout
* 10000000 + 1000000
1537 if (EFI_ERROR (StatCode
)) {
1538 gBS
->CloseEvent (TimeoutEvent
);
1544 DhcpRxBuf
= &PXE_BINL_BUFFER
;
1547 EFI_PXE_BASE_CODE_UDP_PORT BINLSrvPort
;
1554 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
1557 &Private
->EfiBc
.Mode
->StationIp
,
1558 &PSEUDO_DHCP_CLIENT_PORT
,
1565 // make sure from whom we wanted
1567 if (!DhcpRxBuf
->u
.Dhcpv4
.yiaddr
&& !CompareMem (
1569 &((DHCPV4_OP_SERVER_IP
*) DhcpRxBuf
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1])->Ip
,
1570 sizeof (ServerIpPtr
->v4
)
1572 gBS
->CloseEvent (TimeoutEvent
);
1574 // got an ACK from server
1580 gBS
->CloseEvent (TimeoutEvent
);
1584 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1587 // make sure we can get BINL
1588 // send DHCPREQUEST to PXE server
1593 PXE_BASECODE_DEVICE
*Private
,
1597 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1598 EFI_IP_ADDRESS ServerIp
;
1602 DhcpRxBuf
= &RxBuf
[OfferIx
];
1605 // send DHCP request
1606 // if fail return false
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
)
1615 // client IP address - filled in by client if it knows it
1618 ((EFI_IPv4_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
),
1619 &DHCP_REQ_OPTIONS
.OpReqIP
.Ip
,
1620 sizeof (EFI_IPv4_ADDRESS
)
1623 SetMem (&DHCP_REQ_OPTIONS
, sizeof DHCP_REQ_OPTIONS
, OP_PAD
);
1624 DHCPV4_TRANSMIT_BUFFER
.flags
= 0;
1625 DHCPV4_OPTIONS_BUFFER
.End
[0] = OP_END
;
1626 AddRouters (Private
, DhcpRxBuf
);
1627 SaveSecs
= DHCPV4_TRANSMIT_BUFFER
.secs
;
1629 for (Index
= 0; Index
< 3; Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Index
) {
1630 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
1633 // unicast DHCPREQUEST to PXE server
1638 &PseudoDhcpServerPort
,
1639 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
1640 &PSEUDO_DHCP_CLIENT_PORT
1645 if (!GetBINLAck (Private
, &ServerIp
)) {
1649 // early exit failures
1650 // make sure a good ACK
1652 if (!DHCPOfferAckEdit (&PXE_BINL_BUFFER
) || (
1653 !(PXE_BINL_BUFFER
.OpAdds
.Status
& DISCOVER_TYPE
) && !PXE_BINL_BUFFER
.OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1]
1659 Private
->EfiBc
.Mode
->ProxyOfferReceived
= TRUE
;
1663 // failed - reset seconds field, etc.
1665 Private
->EfiBc
.Mode
->RouteTableEntries
= 0;
1669 DHCPV4_TRANSMIT_BUFFER
.secs
= SaveSecs
;
1673 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1677 PXE_BASECODE_DEVICE
*Private
,
1681 if (TryBINL (Private
, OfferIx
)) {
1685 return Release (Private
);
1688 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1691 TryFinishProxyBINL (
1692 PXE_BASECODE_DEVICE
*Private
1697 for (Index
= 0; Index
< Private
->GotProxy
[BINL_IX
]; ++Index
) {
1698 if (TryBINL (Private
, Private
->BinlProxies
[Index
])) {
1703 return Release (Private
);
1706 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
1709 // try to finish DORA - send DHCP request, wait for ACK, check with ARP
1714 PXE_BASECODE_DEVICE
*Private
,
1718 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
1719 EFI_IP_ADDRESS ClientIp
;
1720 EFI_IP_ADDRESS ServerIp
;
1721 EFI_STATUS StatCode
;
1723 EFI_EVENT TimeoutEvent
;
1726 // send DHCP request
1727 // if fail return false
1729 DhcpRxBuf
= &DHCPV4_ACK_BUFFER
;
1730 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
1731 CopyMem (&DHCP_REQ_OPTIONS
, &RequestOpEndStr
, sizeof (RequestOpEndStr
));
1732 // DHCP_REQ_OPTIONS = RequestOpEndStr;
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 ((EFI_D_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 ((EFI_D_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 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2287 IN EFI_PXE_BASE_CODE_PROTOCOL
*This
,
2288 IN BOOLEAN SortOffers
2291 Routine description:
2292 standard DHCP Discover/Offer/Request/Ack session
2293 broadcast DHCPDISCOVER
2295 broadcast DHCPREQUEST
2300 This := Pointer to PxeBc interface
2306 EFI_PXE_BASE_CODE_IP_FILTER Filter
;
2307 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2308 PXE_BASECODE_DEVICE
*Private
;
2309 EFI_STATUS StatCode
;
2312 // Lock the instance data and make sure started
2314 StatCode
= EFI_SUCCESS
;
2317 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
2318 return EFI_INVALID_PARAMETER
;
2321 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2323 if (Private
== NULL
) {
2324 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE pointer == NULL"));
2325 return EFI_INVALID_PARAMETER
;
2328 EfiAcquireLock (&Private
->Lock
);
2330 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2331 DEBUG ((EFI_D_ERROR
, "BC was not started."));
2332 EfiReleaseLock (&Private
->Lock
);
2333 return EFI_NOT_STARTED
;
2336 Filter
.Filters
= EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP
;
2338 Filter
.reserved
= 0;
2340 DEBUG ((EFI_D_INFO
, "\nBcDhcp() Enter. "));
2342 PxebcMode
= Private
->EfiBc
.Mode
;
2344 if (!GetMem (Private
)) {
2345 DEBUG ((EFI_D_ERROR
, "\nBcDhcp() GetMem() failed.\n"));
2346 EfiReleaseLock (&Private
->Lock
);
2347 return EFI_OUT_OF_RESOURCES
;
2350 PxebcMode
->DhcpDiscoverValid
= FALSE
;
2351 PxebcMode
->DhcpAckReceived
= FALSE
;
2352 PxebcMode
->ProxyOfferReceived
= FALSE
;
2354 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DHCP
;
2359 if (Private
->TotalSeconds
== 0) {
2361 // put in seconds field of DHCP send packets
2363 Private
->TotalSeconds
= 4;
2366 if ((StatCode
= DoDhcpDora (Private
, SortOffers
)) == EFI_SUCCESS
) {
2368 // success - copy packets
2370 PxebcMode
->DhcpDiscoverValid
= PxebcMode
->DhcpAckReceived
= TRUE
;
2373 &PxebcMode
->DhcpAck
,
2374 (EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_ACK_PACKET
,
2375 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2378 if (PxebcMode
->ProxyOfferReceived
) {
2380 &PxebcMode
->ProxyOffer
,
2381 (EFI_PXE_BASE_CODE_PACKET
*) &PXE_OFFER_PACKET
,
2382 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2387 // set filter back to unicast
2389 IpFilter (Private
, &Filter
);
2394 // Unlock the instance data
2396 DEBUG ((EFI_D_WARN
, "\nBcDhcp() Exit = %xh ", StatCode
));
2398 EfiReleaseLock (&Private
->Lock
);
2402 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2405 VerifyCredentialOption (
2413 // Fail verification if either pointer is NULL.
2415 if (tx
== NULL
|| rx
== NULL
) {
2419 // Fail verification if tx[0] is not a credential type option
2420 // or if the length is zero or not a multiple of four.
2422 if (tx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| tx
[1] == 0 || tx
[1] % 4 != 0) {
2426 // Fail verification if rx[0] is not a credential type option
2427 // or if the length is not equal to four.
2429 if (rx
[0] != VEND_PXE_CREDENTIAL_TYPES
|| rx
[1] != 4) {
2433 // Look through transmitted credential types for a copy
2434 // of the received credential type.
2436 for (n
= 0; n
< tx
[1]; n
+= 4) {
2437 if (!CompareMem (&tx
[n
+ 2], &rx
[2], 4)) {
2445 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2448 PXE_BASECODE_DEVICE
*Private
,
2451 IN UINT16
*LayerPtr
,
2453 EFI_IP_ADDRESS
*DestPtr
,
2454 PXE_SERVER_LISTS
*ServerListPtr
2457 Routine description:
2458 This function tries to complete the PXE Bootserver and/or boot image
2459 discovery sequence. When this command completes successfully, the
2460 PXEdiscover and PXEreply fields in the BC instance data structure are
2461 updated. If the Info pointer is set to NULL, the discovery information
2462 in the DHCPack and ProxyOffer packets must be valid and will be used.
2463 If Info is not set to NULL, the discovery methods in the Info field
2464 must be set and will be used. When discovering any layer number other
2465 than zero (the credential flag does not count), only unicast discovery
2469 Private := Pointer to PxeBc interface
2480 EFI_PXE_BASE_CODE_UDP_PORT ClientPort
;
2481 EFI_PXE_BASE_CODE_UDP_PORT ServerPort
;
2482 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2483 EFI_STATUS StatCode
;
2484 EFI_EVENT TimeoutEvent
;
2487 PxebcMode
= Private
->EfiBc
.Mode
;
2489 if (DestPtr
->Addr
[0] == 0) {
2490 DEBUG ((EFI_D_WARN
, "\nDoDiscover() !DestPtr->Addr[0]"));
2491 return EFI_INVALID_PARAMETER
;
2494 // seed random number with hardware address
2496 SeedRandom (Private
, *(UINT16
*) &Private
->SimpleNetwork
->Mode
->CurrentAddress
);
2498 if (DestPtr
->Addr
[0] == BroadcastIP
.Addr
[0]) {
2499 ClientPort
= DHCPClientPort
;
2500 ServerPort
= DhcpServerPort
;
2502 ClientPort
= PSEUDO_DHCP_CLIENT_PORT
;
2503 ServerPort
= PseudoDhcpServerPort
;
2507 *LayerPtr
|= PXE_BOOT_LAYER_CREDENTIAL_FLAG
;
2509 *LayerPtr
&= PXE_BOOT_LAYER_MASK
;
2512 for (Private
->Timeout
= 1;
2513 Private
->Timeout
< 5;
2514 Private
->TotalSeconds
= (UINT16
) (Private
->TotalSeconds
+ Private
->Timeout
), ++Private
->Timeout
2516 InitDhcpv4TxBuf (Private
);
2518 // initialize DHCP message structure
2520 DHCPV4_TRANSMIT_BUFFER
.xid
= Random (Private
);
2521 DHCPV4_TRANSMIT_BUFFER
.secs
= HTONS (Private
->TotalSeconds
);
2523 &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2524 &PxebcMode
->StationIp
,
2525 sizeof DHCPV4_TRANSMIT_BUFFER
.ciaddr
2528 DHCPV4_OPTIONS_BUFFER
.DhcpMessageType
.Type
= DHCPREQUEST
;
2529 DISCOVERoptions
.Header
.OpCode
= OP_VENDOR_SPECIFIC
;
2530 DISCOVERoptions
.BootItem
.Header
.OpCode
= VEND_PXE_BOOT_ITEM
;
2531 DISCOVERoptions
.BootItem
.Header
.Length
= DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM
);
2532 DISCOVERoptions
.BootItem
.Type
= HTONS (Type
);
2533 DISCOVERoptions
.BootItem
.Layer
= HTONS (*LayerPtr
);
2536 EFI_BIS_PROTOCOL
*BisPtr
;
2537 BIS_APPLICATION_HANDLE BisAppHandle
;
2538 EFI_BIS_DATA
*BisDataSigInfo
;
2539 EFI_BIS_SIGNATURE_INFO
*BisSigInfo
;
2543 BisPtr
= PxebcBisStart (
2549 if (BisPtr
== NULL
) {
2551 // %%TBD - In order to get here, BIS must have
2552 // been present when PXEBC.Start() was called.
2553 // BIS had to be shutdown/removed/damaged
2554 // before PXEBC.Discover() was called.
2555 // Do we need to document a specific error
2558 return EFI_OUT_OF_RESOURCES
;
2561 // Compute number of credential types.
2563 Index2
= BisDataSigInfo
->Length
/ sizeof (EFI_BIS_SIGNATURE_INFO
);
2565 DISCREDoptions
.Header
.OpCode
= VEND_PXE_CREDENTIAL_TYPES
;
2567 DISCREDoptions
.Header
.Length
= (UINT8
) (Index2
* sizeof (PXE_CREDENTIAL
));
2569 OpLen
= (UINT8
) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
) + sizeof (DHCPV4_OP_HEADER
) + DISCREDoptions
.Header
.Length
);
2571 BisSigInfo
= (EFI_BIS_SIGNATURE_INFO
*) BisDataSigInfo
->Data
;
2573 for (Index
= 0; Index
< Index2
; ++Index
) {
2576 CopyMem (&x
, &BisSigInfo
[Index
], sizeof x
);
2578 CopyMem (&DISCREDoptions
.Credentials
[Index
], &x
, sizeof x
);
2581 PxebcBisStop (BisPtr
, BisAppHandle
, BisDataSigInfo
);
2583 OpLen
= DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS
);
2586 DISCOVERoptions
.Header
.Length
= OpLen
;
2588 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
- 1] = OP_END
;
2589 ((UINT8
*) &DISCOVERoptions
)[sizeof (DHCPV4_OP_HEADER
) + OpLen
] = OP_END
;
2591 StatCode
= DoUdpWrite (
2595 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2599 if (StatCode
!= EFI_SUCCESS
) {
2605 StatCode
= gBS
->CreateEvent (
2613 if (EFI_ERROR (StatCode
)) {
2617 StatCode
= gBS
->SetTimer (
2620 Private
->Timeout
* 10000000 + 1000000
2623 if (EFI_ERROR (StatCode
)) {
2624 gBS
->CloseEvent (TimeoutEvent
);
2631 DHCP_RECEIVE_BUFFER
*RxBufPtr
;
2635 RxBufPtr
= UseBis
? &PXE_BIS_BUFFER
: &PXE_ACK_BUFFER
;
2636 ZeroMem (&Private
->ServerIp
, sizeof (EFI_IP_ADDRESS
));
2642 (EFI_IP_ADDRESS
*) &Private
->ServerIp
,
2644 (EFI_IP_ADDRESS
*) &DHCPV4_TRANSMIT_BUFFER
.ciaddr
,
2652 // check type of response - need PXEClient DHCPACK of proper type with bootfile
2654 if (!(RxBufPtr
->OpAdds
.Status
& PXE_TYPE
) ||
2655 (UseBis
&& (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
)) ||
2656 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_BOOTFILE_IX
- 1] ||
2657 !RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
- 1] ||
2658 !InServerList((EFI_IP_ADDRESS
*)&((DHCPV4_OP_SERVER_IP
*)RxBufPtr
->OpAdds
.PktOptAdds
[OP_DHCP_SERVER_IP_IX
-1])->Ip
, ServerListPtr
)) {
2663 TmpType
= TmpLayer
= 0;
2665 if (RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1]) {
2666 TmpType
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Type
);
2668 if (RxBufPtr
->OpAdds
.Status
& USE_THREE_BYTE
) {
2669 TmpLayer
= (UINT16
) (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
>> 8);
2671 TmpLayer
= NTOHS (((PXE_OP_BOOT_ITEM
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_ITEM_IX
- 1])->Layer
);
2675 if (TmpType
!= Type
) {
2680 if (!RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]) {
2684 if (!VerifyCredentialOption (
2685 (UINT8
*) &DISCREDoptions
.Header
,
2686 (UINT8
*) RxBufPtr
->OpAdds
.PxeOptAdds
[VEND_PXE_CREDENTIAL_TYPES_IX
- 1]
2692 *LayerPtr
= TmpLayer
;
2696 &PxebcMode
->PxeBisReply
,
2697 &RxBufPtr
->u
.Dhcpv4
,
2698 sizeof (EFI_PXE_BASE_CODE_PACKET
)
2701 PxebcMode
->PxeBisReplyReceived
= TRUE
;
2703 StatCode
= DoDiscover (
2705 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2713 gBS
->CloseEvent (TimeoutEvent
);
2717 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= TRUE
;
2720 &PxebcMode
->PxeDiscover
,
2721 &*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
,
2722 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &DHCPV4_TRANSMIT_BUFFER
)
2726 &PxebcMode
->PxeReply
,
2727 &*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
,
2728 sizeof (*(EFI_PXE_BASE_CODE_PACKET
*) &RxBufPtr
->u
.Dhcpv4
)
2731 AddRouters (Private
, RxBufPtr
);
2733 gBS
->CloseEvent (TimeoutEvent
);
2737 gBS
->CloseEvent (TimeoutEvent
);
2745 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2749 PXE_BASECODE_DEVICE
*Private
,
2751 IN UINT16
*LayerPtr
,
2753 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
*DiscoverInfoPtr
,
2754 PXE_SERVER_LISTS
*McastServerListPtr
,
2755 PXE_SERVER_LISTS
*ServerListPtr
2758 Routine Description:
2761 Private := Pointer to PxeBc interface
2766 McastServerListPtr :=
2772 EFI_IP_ADDRESS DestIp
;
2773 EFI_STATUS StatCode
;
2775 DEBUG ((EFI_D_INFO
, "\nDiscover() Type=%d Layer=%d ", Type
, *LayerPtr
));
2778 DEBUG ((EFI_D_INFO
, "BIS "));
2781 // get dest IP addr - mcast, bcast, or unicast
2783 if (DiscoverInfoPtr
->UseMCast
) {
2784 DestIp
.v4
= DiscoverInfoPtr
->ServerMCastIp
.v4
;
2788 "\nDiscover() MCast %d.%d.%d.%d ",
2795 if ((StatCode
= DoDiscover (
2797 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2803 )) != EFI_TIMEOUT
) {
2806 "\nDiscover() status == %r (%Xh)",
2815 if (DiscoverInfoPtr
->UseBCast
) {
2816 DEBUG ((EFI_D_INFO
, "\nDiscver() BCast "));
2818 if ((StatCode
= DoDiscover (
2820 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2826 )) != EFI_TIMEOUT
) {
2828 DEBUG ((EFI_D_WARN
, "\nDiscover() status == %r (%Xh)", StatCode
, StatCode
));
2834 if (DiscoverInfoPtr
->UseUCast
) {
2839 "\nDiscover() UCast IP#=%d ",
2840 ServerListPtr
->Ipv4List
.IpCount
)
2843 for (Index
= 0; Index
< ServerListPtr
->Ipv4List
.IpCount
; ++Index
) {
2844 CopyMem (&DestIp
, &ServerListPtr
->Ipv4List
.IpList
[Index
], 4);
2848 "\nDiscover() UCast %d.%d.%d.%d ",
2855 if ((StatCode
= DoDiscover (
2857 EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP
| EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT
,
2863 )) != EFI_TIMEOUT
) {
2866 "\nDiscover() status == %r (%Xh)",
2876 DEBUG ((EFI_D_WARN
, "\nDiscover() TIMEOUT"));
2881 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2888 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
2890 IN UINT16
*LayerPtr
,
2892 IN EFI_PXE_BASE_CODE_DISCOVER_INFO
* DiscoverInfoPtr OPTIONAL
2895 Routine description:
2907 EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo
;
2908 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
2909 DHCP_RECEIVE_BUFFER
*DhcpRxBuf
;
2910 PXE_SERVER_LISTS DefaultSrvList
;
2911 PXE_SERVER_LISTS
*ServerListPtr
;
2912 PXE_SERVER_LISTS
*McastServerListPtr
;
2917 BOOLEAN AcquiredSrvList
;
2918 EFI_STATUS StatCode
;
2919 PXE_BASECODE_DEVICE
*Private
;
2922 // Lock the instance data and make sure started
2924 StatCode
= EFI_SUCCESS
;
2927 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
2928 return EFI_INVALID_PARAMETER
;
2931 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
2933 if (Private
== NULL
) {
2934 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
2935 return EFI_INVALID_PARAMETER
;
2938 EfiAcquireLock (&Private
->Lock
);
2940 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
2941 DEBUG ((EFI_D_ERROR
, "BC was not started."));
2942 EfiReleaseLock (&Private
->Lock
);
2943 return EFI_NOT_STARTED
;
2946 ServerListPtr
= NULL
;
2947 McastServerListPtr
= NULL
;
2948 AcquiredSrvList
= FALSE
;
2950 PxebcMode
= Private
->EfiBc
.Mode
;
2952 if (!GetMem (Private
)) {
2953 EfiReleaseLock (&Private
->Lock
);
2954 return EFI_OUT_OF_RESOURCES
;
2958 if (!PxebcMode
->BisSupported
) {
2959 EfiReleaseLock (&Private
->Lock
);
2960 return EFI_INVALID_PARAMETER
;
2964 Private
->Function
= EFI_PXE_BASE_CODE_FUNCTION_DISCOVER
;
2966 if (Private
->TotalSeconds
== 0) {
2968 // put in seconds field of DHCP send packets
2970 Private
->TotalSeconds
= 4;
2973 ZeroMem (&DefaultInfo
, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO
));
2976 // if layer number not zero, use previous discover
2978 if (*LayerPtr
!= 0) {
2979 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0"));
2981 if (DiscoverInfoPtr
!= NULL
) {
2982 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n"));
2984 EfiReleaseLock (&Private
->Lock
);
2985 return EFI_INVALID_PARAMETER
;
2988 if (!PxebcMode
->PxeDiscoverValid
) {
2989 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n"));
2991 EfiReleaseLock (&Private
->Lock
);
2992 return EFI_INVALID_PARAMETER
;
2995 if (!PxebcMode
->PxeReplyReceived
) {
2996 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n"));
2998 EfiReleaseLock (&Private
->Lock
);
2999 return EFI_INVALID_PARAMETER
;
3002 if (UseBis
&& !PxebcMode
->PxeBisReplyReceived
) {
3003 DEBUG ((EFI_D_WARN
, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n"));
3005 EfiReleaseLock (&Private
->Lock
);
3006 return EFI_INVALID_PARAMETER
;
3009 DefaultInfo
.UseUCast
= TRUE
;
3010 DiscoverInfoPtr
= &DefaultInfo
;
3012 DefaultSrvList
.Ipv4List
.IpCount
= 1;
3013 CopyMem (&DefaultSrvList
.Ipv4List
.IpList
[0], &Private
->ServerIp
, 4);
3015 ServerListPtr
= &DefaultSrvList
;
3018 // layer is zero - see if info is supplied or if we need to use info from a cached offer
3020 else if (!DiscoverInfoPtr
) {
3022 // not supplied - generate it
3023 // make sure that there is cached, appropriate information
3024 // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail
3026 DhcpRxBuf
= (PxebcMode
->ProxyOfferReceived
) ? &PXE_OFFER_BUFFER
: &DHCPV4_ACK_BUFFER
;
3028 if (!PxebcMode
->DhcpAckReceived
|| !(DhcpRxBuf
->OpAdds
.Status
& DISCOVER_TYPE
)) {
3029 DEBUG ((EFI_D_WARN
, "\nBcDiscover() !ack && !proxy"));
3030 EfiReleaseLock (&Private
->Lock
);
3031 return EFI_INVALID_PARAMETER
;
3034 DiscoverInfoPtr
= &DefaultInfo
;
3036 LocalPtr
.OpPtr
= DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_CONTROL_IX
- 1];
3039 // if multicast enabled, need multicast address
3041 if (!(LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_MCAST
)) {
3042 DefaultInfo
.UseMCast
= TRUE
;
3045 ((EFI_IPv4_ADDRESS
*) &DefaultInfo
.ServerMCastIp
),
3046 &((DHCPV4_OP_IP_ADDRESS
*) DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_DISCOVERY_MCAST_ADDR_IX
- 1])->Ip
,
3047 sizeof (EFI_IPv4_ADDRESS
)
3051 DefaultInfo
.UseBCast
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& DISABLE_BCAST
) == 0);
3053 DefaultInfo
.MustUseList
= (BOOLEAN
) ((LocalPtr
.DiscoveryControl
->ControlBits
& USE_ACCEPT_LIST
) != 0);
3055 DefaultInfo
.UseUCast
= (BOOLEAN
)
3057 (DefaultInfo
.MustUseList
) ||
3058 ((LocalPtr
.DiscoveryControl
->ControlBits
& (DISABLE_MCAST
| DISABLE_BCAST
)) == (DISABLE_MCAST
| DISABLE_BCAST
))
3061 if ((DefaultInfo
.UseUCast
| DefaultInfo
.MustUseList
) && !ExtractBootServerList (
3063 DhcpRxBuf
->OpAdds
.PxeOptAdds
[VEND_PXE_BOOT_SERVERS_IX
- 1],
3066 DEBUG ((EFI_D_WARN
, "\nBcDiscover() type not in list"));
3067 EfiReleaseLock (&Private
->Lock
);
3068 return EFI_INVALID_PARAMETER
;
3072 // Info supplied - make SrvList if required
3073 // if we use ucast discovery or must use list, there better be one
3075 else if (DiscoverInfoPtr
->UseUCast
|| DiscoverInfoPtr
->MustUseList
) {
3077 // there better be a list
3079 if (DiscoverInfoPtr
->IpCnt
== 0) {
3080 DEBUG ((EFI_D_WARN
, "\nBcDiscover() no bootserver list"));
3081 EfiReleaseLock (&Private
->Lock
);
3082 return EFI_INVALID_PARAMETER
;
3087 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3088 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3089 if (DiscoverInfoPtr
->SrvList
[Index
].AcceptAnyResponse
) {
3091 DEBUG ((EFI_D_WARN
, "\nBcDiscover() accept any?"));
3092 EfiReleaseLock (&Private
->Lock
);
3093 return EFI_INVALID_PARAMETER
;
3096 DefaultSrvList
.Ipv4List
.IpCount
= 0;
3097 ServerListPtr
= &DefaultSrvList
;
3107 DEBUG ((EFI_D_WARN
, "\nBcDiscover() !Index2?"));
3108 EfiReleaseLock (&Private
->Lock
);
3109 return EFI_INVALID_PARAMETER
;
3112 if (ServerListPtr
== NULL
) {
3113 Status
= gBS
->AllocatePool (
3114 EfiBootServicesData
,
3115 sizeof (PXEV4_SERVER_LIST
) + (Index2
- 1) * sizeof (EFI_IPv4_ADDRESS
),
3116 (VOID
**) &ServerListPtr
3119 if (EFI_ERROR (Status
) || ServerListPtr
== NULL
) {
3120 ServerListPtr
= NULL
;
3121 EfiReleaseLock (&Private
->Lock
);
3122 return EFI_OUT_OF_RESOURCES
;
3125 // build an array of IP addresses from the server list
3127 AcquiredSrvList
= TRUE
;
3128 ServerListPtr
->Ipv4List
.IpCount
= (UINT8
) Index2
;
3130 for (Index
= Index2
= 0; Index
< DiscoverInfoPtr
->IpCnt
; ++Index
) {
3131 if (DiscoverInfoPtr
->SrvList
[Index
].Type
== Type
) {
3133 &ServerListPtr
->Ipv4List
.IpList
[Index2
++],
3134 &DiscoverInfoPtr
->SrvList
[Index
].IpAddr
.v4
,
3135 sizeof ServerListPtr
->Ipv4List
.IpList
[0]
3142 if (DiscoverInfoPtr
->MustUseList
) {
3143 McastServerListPtr
= ServerListPtr
;
3146 if (!(DiscoverInfoPtr
->UseMCast
|| DiscoverInfoPtr
->UseBCast
|| DiscoverInfoPtr
->UseUCast
)) {
3147 DEBUG ((EFI_D_WARN
, "\nBcDiscover() Nothing to use!\n"));
3149 EfiReleaseLock (&Private
->Lock
);
3150 return EFI_INVALID_PARAMETER
;
3153 PxebcMode
->PxeDiscoverValid
= PxebcMode
->PxeReplyReceived
= PxebcMode
->PxeBisReplyReceived
= FALSE
;
3155 StatCode
= Discover (
3165 if (AcquiredSrvList
) {
3166 gBS
->FreePool (ServerListPtr
);
3172 // Unlock the instance data
3176 "\nBcDiscover() status == %r (%Xh)\n",
3181 EfiReleaseLock (&Private
->Lock
);
3185 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3189 IN EFI_PXE_BASE_CODE_PROTOCOL
* This
,
3190 BOOLEAN
*NewDhcpDiscoverValid
, OPTIONAL
3191 BOOLEAN
*NewDhcpAckReceived
, OPTIONAL
3192 BOOLEAN
*NewProxyOfferReceived
, OPTIONAL
3193 BOOLEAN
*NewPxeDiscoverValid
, OPTIONAL
3194 BOOLEAN
*NewPxeReplyReceived
, OPTIONAL
3195 BOOLEAN
*NewPxeBisReplyReceived
, OPTIONAL
3196 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpDiscover
, OPTIONAL
3197 IN EFI_PXE_BASE_CODE_PACKET
* NewDhcpAck
, OPTIONAL
3198 IN EFI_PXE_BASE_CODE_PACKET
* NewProxyOffer
, OPTIONAL
3199 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeDiscover
, OPTIONAL
3200 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeReply
, OPTIONAL
3201 IN EFI_PXE_BASE_CODE_PACKET
* NewPxeBisReply OPTIONAL
3204 Routine description:
3211 EFI_PXE_BASE_CODE_MODE
*PxebcMode
;
3213 EFI_STATUS StatCode
;
3214 PXE_BASECODE_DEVICE
*Private
;
3217 // Lock the instance data and make sure started
3219 StatCode
= EFI_SUCCESS
;
3222 DEBUG ((EFI_D_ERROR
, "BC *This pointer == NULL"));
3223 return EFI_INVALID_PARAMETER
;
3226 Private
= CR (This
, PXE_BASECODE_DEVICE
, EfiBc
, PXE_BASECODE_DEVICE_SIGNATURE
);
3228 if (Private
== NULL
) {
3229 DEBUG ((EFI_D_ERROR
, "PXE_BASECODE_DEVICE poiner == NULL"));
3230 return EFI_INVALID_PARAMETER
;
3233 EfiAcquireLock (&Private
->Lock
);
3235 if (This
->Mode
== NULL
|| !This
->Mode
->Started
) {
3236 DEBUG ((EFI_D_ERROR
, "BC was not started."));
3237 EfiReleaseLock (&Private
->Lock
);
3238 return EFI_NOT_STARTED
;
3241 PxebcMode
= Private
->EfiBc
.Mode
;
3243 if (Private
->DhcpPacketBuffer
== NULL
) {
3244 Status
= gBS
->AllocatePool (
3245 EfiBootServicesData
,
3246 sizeof (DHCP_RECEIVE_BUFFER
) * (PXE_BIS_INDEX
+ 1),
3247 &Private
->DhcpPacketBuffer
3250 if (EFI_ERROR (Status
) || Private
->DhcpPacketBuffer
== NULL
) {
3251 Private
->DhcpPacketBuffer
= NULL
;
3252 EfiReleaseLock (&Private
->Lock
);
3253 return EFI_OUT_OF_RESOURCES
;
3262 Private
->FileSize
= 0;
3263 if (NewDhcpDiscoverValid
!= NULL
) {
3264 PxebcMode
->DhcpDiscoverValid
= *NewDhcpDiscoverValid
;
3267 if (NewDhcpAckReceived
!= NULL
) {
3268 PxebcMode
->DhcpAckReceived
= *NewDhcpAckReceived
;
3271 if (NewProxyOfferReceived
!= NULL
) {
3272 PxebcMode
->ProxyOfferReceived
= *NewProxyOfferReceived
;
3275 if (NewPxeDiscoverValid
!= NULL
) {
3276 PxebcMode
->PxeDiscoverValid
= *NewPxeDiscoverValid
;
3279 if (NewPxeReplyReceived
!= NULL
) {
3280 PxebcMode
->PxeReplyReceived
= *NewPxeReplyReceived
;
3283 if (NewPxeBisReplyReceived
!= NULL
) {
3284 PxebcMode
->PxeBisReplyReceived
= *NewPxeBisReplyReceived
;
3287 if (NewDhcpDiscover
!= NULL
) {
3289 &PxebcMode
->DhcpDiscover
,
3291 sizeof *NewDhcpDiscover
3295 if (NewDhcpAck
!= NULL
) {
3296 CopyParse (Private
, &PxebcMode
->DhcpAck
, NewDhcpAck
, DHCPV4_ACK_INDEX
);
3299 if (NewProxyOffer
!= NULL
) {
3300 CopyParse (Private
, &PxebcMode
->ProxyOffer
, NewProxyOffer
, PXE_OFFER_INDEX
);
3303 if (NewPxeDiscover
!= NULL
) {
3305 &PxebcMode
->PxeDiscover
,
3307 sizeof *NewPxeDiscover
3311 if (NewPxeReply
!= NULL
) {
3312 CopyParse (Private
, &PxebcMode
->PxeReply
, NewPxeReply
, PXE_ACK_INDEX
);
3315 if (NewPxeBisReply
!= NULL
) {
3316 CopyParse (Private
, &PxebcMode
->PxeBisReply
, NewPxeBisReply
, PXE_BIS_INDEX
);
3319 // Unlock the instance data
3321 EfiReleaseLock (&Private
->Lock
);
3325 /* eof - pxe_bc_dhcp.c */