3 Copyright (c) 2006 - 2008, 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.
18 This file implement the EFI_DHCP4_PROTOCOL interface.
24 #include "Dhcp4Impl.h"
27 Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.
29 The GetModeData() function returns the current operating mode and cached data
30 packet for the EFI DHCPv4 Protocol driver.
32 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
33 @param Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.
35 @retval EFI_SUCCESS The mode data was returned.
36 @retval EFI_INVALID_PARAMETER This is NULL.
42 IN EFI_DHCP4_PROTOCOL
*This
,
43 OUT EFI_DHCP4_MODE_DATA
*Dhcp4ModeData
47 Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.
49 The Configure() function is used to initialize, change, or reset the operational
50 settings of the EFI DHCPv4 Protocol driver for the communication device on which
51 the EFI DHCPv4 Service Binding Protocol is installed. This function can be
52 successfully called only if both of the following are true:
53 * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,
54 Dhcp4InitReboot, or Dhcp4Bound states.
55 * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI
56 DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4
58 When this driver is in the Dhcp4Stopped state, it can transfer into one of the
59 following two possible initial states:
62 The driver can transfer into these states by calling Configure() with a non-NULL
63 Dhcp4CfgData. The driver will transfer into the appropriate state based on the
64 supplied client network address in the ClientAddress parameter and DHCP options
65 in the OptionList parameter as described in RFC 2131.
66 When Configure() is called successfully while Dhcp4CfgData is set to NULL, the
67 default configuring data will be reset in the EFI DHCPv4 Protocol driver and
68 the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance
69 wants to make it possible for another instance to configure the EFI DHCPv4 Protocol
70 driver, it must call this function with Dhcp4CfgData set to NULL.
72 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
73 @param Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.
75 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or
76 Dhcp4InitReboot state, if the original state of this driver
77 was Dhcp4Stopped and the value of Dhcp4CfgData was
78 not NULL. Otherwise, the state was left unchanged.
79 @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the
80 Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;
81 Or onother instance of this EFI DHCPv4 Protocol driver is already
82 in a valid configured state.
83 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
84 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
85 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
91 IN EFI_DHCP4_PROTOCOL
*This
,
92 IN EFI_DHCP4_CONFIG_DATA
*Dhcp4CfgData OPTIONAL
96 Starts the DHCP configuration process.
98 The Start() function starts the DHCP configuration process. This function can
99 be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or
100 Dhcp4InitReboot state.
101 If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol
102 driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the
103 Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.
104 If the process aborts, either by the user or by some unexpected network error,
105 the state is restored to the Dhcp4Init state. The Start() function can be called
106 again to restart the process.
107 Refer to RFC 2131 for precise state transitions during this process. At the
108 time when each event occurs in this process, the callback function that was set
109 by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this
110 opportunity to control the process.
112 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
113 @param CompletionEvent If not NULL, indicates the event that will be signaled when the
114 EFI DHCPv4 Protocol driver is transferred into the
115 Dhcp4Bound state or when the DHCP process is aborted.
116 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
117 check the completion status. If NULL,
118 EFI_DHCP4_PROTOCOL.Start() will wait until the driver
119 is transferred into the Dhcp4Bound state or the process fails.
121 @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed
122 when CompletionEvent is NULL.
123 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
124 state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.
125 @retval EFI_INVALID_PARAMETER This is NULL.
126 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
127 @retval EFI_TIMEOUT The DHCP configuration process failed because no response was
128 received from the server within the specified timeout value.
129 @retval EFI_ABORTED The user aborted the DHCP process.
130 @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the
132 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
138 IN EFI_DHCP4_PROTOCOL
*This
,
139 IN EFI_EVENT CompletionEvent OPTIONAL
143 Extends the lease time by sending a request packet.
145 The RenewRebind() function is used to manually extend the lease time when the
146 EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has
147 not expired yet. This function will send a request packet to the previously
148 found server (or to any server when RebindRequest is TRUE) and transfer the
149 state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is
150 TRUE). When a response is received, the state is returned to Dhcp4Bound.
151 If no response is received before the try count is exceeded (the RequestTryCount
152 field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that
153 was issued by the previous server expires, the driver will return to the Dhcp4Bound
154 state and the previous configuration is restored. The outgoing and incoming packets
155 can be captured by the EFI_DHCP4_CALLBACK function.
157 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
158 @param RebindRequest If TRUE, this function broadcasts the request packets and enters
159 the Dhcp4Rebinding state. Otherwise, it sends a unicast
160 request packet and enters the Dhcp4Renewing state.
161 @param CompletionEvent If not NULL, this event is signaled when the renew/rebind phase
162 completes or some error occurs.
163 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
164 check the completion status. If NULL,
165 EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait
166 until the DHCP process finishes.
168 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the
169 Dhcp4Renewing state or is back to the Dhcp4Bound state.
170 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
171 state. EFI_DHCP4_PROTOCOL.Configure() needs to
173 @retval EFI_INVALID_PARAMETER This is NULL.
174 @retval EFI_TIMEOUT There was no response from the server when the try count was
176 @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.
177 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
182 EfiDhcp4RenewRebind (
183 IN EFI_DHCP4_PROTOCOL
*This
,
184 IN BOOLEAN RebindRequest
,
185 IN EFI_EVENT CompletionEvent OPTIONAL
189 Releases the current address configuration.
191 The Release() function releases the current configured IP address by doing either
193 * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the
195 * Setting the previously assigned IP address that was provided with the
196 EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in
197 Dhcp4InitReboot state
198 After a successful call to this function, the EFI DHCPv4 Protocol driver returns
199 to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.
201 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
203 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.
204 @retval EFI_INVALID_PARAMETER This is NULL.
205 @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.
206 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
212 IN EFI_DHCP4_PROTOCOL
*This
216 Stops the current address configuration.
218 The Stop() function is used to stop the DHCP configuration process. After this
219 function is called successfully, the EFI DHCPv4 Protocol driver is transferred
220 into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called
221 before DHCP configuration process can be started again. This function can be
222 called when the EFI DHCPv4 Protocol driver is in any state.
224 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
226 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.
227 @retval EFI_INVALID_PARAMETER This is NULL.
233 IN EFI_DHCP4_PROTOCOL
*This
237 Builds a DHCP packet, given the options to be appended or deleted or replaced.
239 The Build() function is used to assemble a new packet from the original packet
240 by replacing or deleting existing options or appending new options. This function
241 does not change any state of the EFI DHCPv4 Protocol driver and can be used at
244 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
245 @param SeedPacket Initial packet to be used as a base for building new packet.
246 @param DeleteCount Number of opcodes in the DeleteList.
247 @param DeleteList List of opcodes to be deleted from the seed packet.
248 Ignored if DeleteCount is zero.
249 @param AppendCount Number of entries in the OptionList.
250 @param AppendList Pointer to a DHCP option list to be appended to SeedPacket.
251 If SeedPacket also contains options in this list, they are
252 replaced by new options (except pad option). Ignored if
253 AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION
254 @param NewPacket Pointer to storage for the pointer to the new allocated packet.
255 Use the EFI Boot Service FreePool() on the resulting pointer
256 when done with the packet.
258 @retval EFI_SUCCESS The new packet was built.
259 @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.
260 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
266 IN EFI_DHCP4_PROTOCOL
*This
,
267 IN EFI_DHCP4_PACKET
*SeedPacket
,
268 IN UINT32 DeleteCount
,
269 IN UINT8
*DeleteList OPTIONAL
,
270 IN UINT32 AppendCount
,
271 IN EFI_DHCP4_PACKET_OPTION
*AppendList
[] OPTIONAL
,
272 OUT EFI_DHCP4_PACKET
**NewPacket
276 Transmits a DHCP formatted packet and optionally waits for responses.
278 The TransmitReceive() function is used to transmit a DHCP packet and optionally
279 wait for the response from servers. This function does not change the state of
280 the EFI DHCPv4 Protocol driver and thus can be used at any time.
282 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
283 @param Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.
285 @retval EFI_SUCCESS The packet was successfully queued for transmission.
286 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
287 @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call
288 this function after collection process completes.
289 @retval EFI_NO_MAPPING The default station address is not available yet.
290 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
291 @retval Others Some other unexpected error occurred.
296 EfiDhcp4TransmitReceive (
297 IN EFI_DHCP4_PROTOCOL
*This
,
298 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
*Token
302 Parses the packed DHCP option data.
304 The Parse() function is used to retrieve the option list from a DHCP packet.
305 If *OptionCount isn’t zero, and there is enough space for all the DHCP options
306 in the Packet, each element of PacketOptionList is set to point to somewhere in
307 the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,
308 the caller should reassemble the parsed DHCP options to get the finial result.
309 If *OptionCount is zero or there isn’t enough space for all of them, the number
310 of DHCP options in the Packet is returned in OptionCount.
312 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
313 @param Packet Pointer to packet to be parsed.
314 @param OptionCount On input, the number of entries in the PacketOptionList.
315 On output, the number of entries that were written into the
317 @param PacketOptionList List of packet option entries to be filled in. End option or pad
318 options are not included.
320 @retval EFI_SUCCESS The packet was successfully parsed.
321 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
322 @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:
323 1) *OptionCount is smaller than the number of options that
324 were found in the Packet.
325 2) PacketOptionList is NULL.
331 IN EFI_DHCP4_PROTOCOL
*This
,
332 IN EFI_DHCP4_PACKET
*Packet
,
333 IN OUT UINT32
*OptionCount
,
334 OUT EFI_DHCP4_PACKET_OPTION
*PacketOptionList
[] OPTIONAL
337 EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate
= {
345 EfiDhcp4TransmitReceive
,
350 Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.
352 The GetModeData() function returns the current operating mode and cached data
353 packet for the EFI DHCPv4 Protocol driver.
355 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
356 @param Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.
358 @retval EFI_SUCCESS The mode data was returned.
359 @retval EFI_INVALID_PARAMETER This is NULL.
364 EfiDhcp4GetModeData (
365 IN EFI_DHCP4_PROTOCOL
*This
,
366 OUT EFI_DHCP4_MODE_DATA
*Dhcp4ModeData
369 DHCP_PROTOCOL
*Instance
;
370 DHCP_SERVICE
*DhcpSb
;
371 DHCP_PARAMETER
*Para
;
376 // First validate the parameters.
378 if ((This
== NULL
) || (Dhcp4ModeData
== NULL
)) {
379 return EFI_INVALID_PARAMETER
;
382 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
384 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
385 DhcpSb
= Instance
->Service
;
388 // Caller can use GetModeData to retrieve current DHCP states
389 // no matter whether it is the active child or not.
391 Dhcp4ModeData
->State
= (EFI_DHCP4_STATE
) DhcpSb
->DhcpState
;
392 CopyMem (&Dhcp4ModeData
->ConfigData
, &DhcpSb
->ActiveConfig
, sizeof (Dhcp4ModeData
->ConfigData
));
393 CopyMem (&Dhcp4ModeData
->ClientMacAddress
, &DhcpSb
->Mac
, sizeof (Dhcp4ModeData
->ClientMacAddress
));
395 Ip
= HTONL (DhcpSb
->ClientAddr
);
396 CopyMem (&Dhcp4ModeData
->ClientAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
398 Ip
= HTONL (DhcpSb
->Netmask
);
399 CopyMem (&Dhcp4ModeData
->SubnetMask
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
401 Ip
= HTONL (DhcpSb
->ServerAddr
);
402 CopyMem (&Dhcp4ModeData
->ServerAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
407 Ip
= HTONL (Para
->Router
);
408 CopyMem (&Dhcp4ModeData
->RouterAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
409 Dhcp4ModeData
->LeaseTime
= Para
->Lease
;
411 ZeroMem (&Dhcp4ModeData
->RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
412 Dhcp4ModeData
->LeaseTime
= 0xffffffff;
415 Dhcp4ModeData
->ReplyPacket
= DhcpSb
->Selected
;
417 gBS
->RestoreTPL (OldTpl
);
423 Free the resource related to the configure parameters.
424 DHCP driver will make a copy of the user's configure
425 such as the time out value.
427 @param Config The DHCP configure data
434 IN OUT EFI_DHCP4_CONFIG_DATA
*Config
439 if (Config
->DiscoverTimeout
!= NULL
) {
440 gBS
->FreePool (Config
->DiscoverTimeout
);
443 if (Config
->RequestTimeout
!= NULL
) {
444 gBS
->FreePool (Config
->RequestTimeout
);
447 if (Config
->OptionList
!= NULL
) {
448 for (Index
= 0; Index
< Config
->OptionCount
; Index
++) {
449 if (Config
->OptionList
[Index
] != NULL
) {
450 gBS
->FreePool (Config
->OptionList
[Index
]);
454 gBS
->FreePool (Config
->OptionList
);
457 ZeroMem (Config
, sizeof (EFI_DHCP4_CONFIG_DATA
));
462 Allocate memory for configure parameter such as timeout value for Dst,
463 then copy the configure parameter from Src to Dst.
465 @param Dst The destination DHCP configure data.
466 @param Src The source DHCP configure data.
468 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
469 @retval EFI_SUCCESS The configure is copied.
474 OUT EFI_DHCP4_CONFIG_DATA
*Dst
,
475 IN EFI_DHCP4_CONFIG_DATA
*Src
478 EFI_DHCP4_PACKET_OPTION
**DstOptions
;
479 EFI_DHCP4_PACKET_OPTION
**SrcOptions
;
483 CopyMem (Dst
, Src
, sizeof (*Dst
));
484 Dst
->DiscoverTimeout
= NULL
;
485 Dst
->RequestTimeout
= NULL
;
486 Dst
->OptionList
= NULL
;
489 // Allocate a memory then copy DiscoverTimeout to it
491 if (Src
->DiscoverTimeout
!= NULL
) {
492 Len
= Src
->DiscoverTryCount
* sizeof (UINT32
);
493 Dst
->DiscoverTimeout
= AllocatePool (Len
);
495 if (Dst
->DiscoverTimeout
== NULL
) {
496 return EFI_OUT_OF_RESOURCES
;
499 for (Index
= 0; Index
< Src
->DiscoverTryCount
; Index
++) {
500 Dst
->DiscoverTimeout
[Index
] = MAX (Src
->DiscoverTimeout
[Index
], 1);
505 // Allocate a memory then copy RequestTimeout to it
507 if (Src
->RequestTimeout
!= NULL
) {
508 Len
= Src
->RequestTryCount
* sizeof (UINT32
);
509 Dst
->RequestTimeout
= AllocatePool (Len
);
511 if (Dst
->RequestTimeout
== NULL
) {
515 for (Index
= 0; Index
< Src
->RequestTryCount
; Index
++) {
516 Dst
->RequestTimeout
[Index
] = MAX (Src
->RequestTimeout
[Index
], 1);
521 // Allocate an array of dhcp option point, then allocate memory
522 // for each option and copy the source option to it
524 if (Src
->OptionList
!= NULL
) {
525 Len
= Src
->OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*);
526 Dst
->OptionList
= AllocateZeroPool (Len
);
528 if (Dst
->OptionList
== NULL
) {
532 DstOptions
= Dst
->OptionList
;
533 SrcOptions
= Src
->OptionList
;
535 for (Index
= 0; Index
< Src
->OptionCount
; Index
++) {
536 Len
= sizeof (EFI_DHCP4_PACKET_OPTION
) + MAX (SrcOptions
[Index
]->Length
- 1, 0);
538 DstOptions
[Index
] = AllocatePool (Len
);
540 if (DstOptions
[Index
] == NULL
) {
544 CopyMem (DstOptions
[Index
], SrcOptions
[Index
], Len
);
551 DhcpCleanConfigure (Dst
);
552 return EFI_OUT_OF_RESOURCES
;
557 Give up the control of the DHCP service to let other child
558 resume. Don't change the service's DHCP state and the Client
559 address and option list configure as required by RFC2131.
561 @param DhcpSb The DHCP service instance.
568 IN DHCP_SERVICE
*DhcpSb
571 EFI_DHCP4_CONFIG_DATA
*Config
;
573 Config
= &DhcpSb
->ActiveConfig
;
575 DhcpSb
->ServiceState
= DHCP_UNCONFIGED
;
576 DhcpSb
->ActiveChild
= NULL
;
578 if (Config
->DiscoverTimeout
!= NULL
) {
579 gBS
->FreePool (Config
->DiscoverTimeout
);
581 Config
->DiscoverTryCount
= 0;
582 Config
->DiscoverTimeout
= NULL
;
585 if (Config
->RequestTimeout
!= NULL
) {
586 gBS
->FreePool (Config
->RequestTimeout
);
588 Config
->RequestTryCount
= 0;
589 Config
->RequestTimeout
= NULL
;
592 Config
->Dhcp4Callback
= NULL
;
593 Config
->CallbackContext
= NULL
;
598 Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.
600 The Configure() function is used to initialize, change, or reset the operational
601 settings of the EFI DHCPv4 Protocol driver for the communication device on which
602 the EFI DHCPv4 Service Binding Protocol is installed. This function can be
603 successfully called only if both of the following are true:
604 * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,
605 Dhcp4InitReboot, or Dhcp4Bound states.
606 * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI
607 DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4
609 When this driver is in the Dhcp4Stopped state, it can transfer into one of the
610 following two possible initial states:
613 The driver can transfer into these states by calling Configure() with a non-NULL
614 Dhcp4CfgData. The driver will transfer into the appropriate state based on the
615 supplied client network address in the ClientAddress parameter and DHCP options
616 in the OptionList parameter as described in RFC 2131.
617 When Configure() is called successfully while Dhcp4CfgData is set to NULL, the
618 default configuring data will be reset in the EFI DHCPv4 Protocol driver and
619 the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance
620 wants to make it possible for another instance to configure the EFI DHCPv4 Protocol
621 driver, it must call this function with Dhcp4CfgData set to NULL.
623 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
624 @param Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.
626 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or
627 Dhcp4InitReboot state, if the original state of this driver
628 was Dhcp4Stopped and the value of Dhcp4CfgData was
629 not NULL. Otherwise, the state was left unchanged.
630 @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the
631 Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;
632 Or onother instance of this EFI DHCPv4 Protocol driver is already
633 in a valid configured state.
634 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
635 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
636 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
642 IN EFI_DHCP4_PROTOCOL
*This
,
643 IN EFI_DHCP4_CONFIG_DATA
*Dhcp4CfgData OPTIONAL
646 EFI_DHCP4_CONFIG_DATA
*Config
;
647 DHCP_PROTOCOL
*Instance
;
648 DHCP_SERVICE
*DhcpSb
;
655 // First validate the parameters
658 return EFI_INVALID_PARAMETER
;
661 if (Dhcp4CfgData
!= NULL
) {
662 if (Dhcp4CfgData
->DiscoverTryCount
&& (Dhcp4CfgData
->DiscoverTimeout
== NULL
)) {
663 return EFI_INVALID_PARAMETER
;
666 if (Dhcp4CfgData
->RequestTryCount
&& (Dhcp4CfgData
->RequestTimeout
== NULL
)) {
667 return EFI_INVALID_PARAMETER
;
670 if (Dhcp4CfgData
->OptionCount
&& (Dhcp4CfgData
->OptionList
== NULL
)) {
671 return EFI_INVALID_PARAMETER
;
674 CopyMem (&Ip
, &Dhcp4CfgData
->ClientAddress
, sizeof (IP4_ADDR
));
676 if ((Ip
!= 0) && !Ip4IsUnicast (NTOHL (Ip
), 0)) {
678 return EFI_INVALID_PARAMETER
;
682 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
684 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
685 return EFI_INVALID_PARAMETER
;
688 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
690 DhcpSb
= Instance
->Service
;
691 Config
= &DhcpSb
->ActiveConfig
;
693 Status
= EFI_ACCESS_DENIED
;
695 if ((DhcpSb
->DhcpState
!= Dhcp4Stopped
) &&
696 (DhcpSb
->DhcpState
!= Dhcp4Init
) &&
697 (DhcpSb
->DhcpState
!= Dhcp4InitReboot
) &&
698 (DhcpSb
->DhcpState
!= Dhcp4Bound
)) {
703 if ((DhcpSb
->ActiveChild
!= NULL
) && (DhcpSb
->ActiveChild
!= Instance
)) {
707 if (Dhcp4CfgData
!= NULL
) {
708 Status
= EFI_OUT_OF_RESOURCES
;
709 DhcpCleanConfigure (Config
);
711 if (EFI_ERROR (DhcpCopyConfigure (Config
, Dhcp4CfgData
))) {
715 DhcpSb
->UserOptionLen
= 0;
717 for (Index
= 0; Index
< Dhcp4CfgData
->OptionCount
; Index
++) {
718 DhcpSb
->UserOptionLen
+= Dhcp4CfgData
->OptionList
[Index
]->Length
+ 2;
721 DhcpSb
->ActiveChild
= Instance
;
723 if (DhcpSb
->DhcpState
== Dhcp4Stopped
) {
724 DhcpSb
->ClientAddr
= EFI_NTOHL (Dhcp4CfgData
->ClientAddress
);
726 if (DhcpSb
->ClientAddr
!= 0) {
727 DhcpSb
->DhcpState
= Dhcp4InitReboot
;
729 DhcpSb
->DhcpState
= Dhcp4Init
;
733 DhcpSb
->ServiceState
= DHCP_CONFIGED
;
734 Status
= EFI_SUCCESS
;
736 } else if (DhcpSb
->ActiveChild
== Instance
) {
737 Status
= EFI_SUCCESS
;
738 DhcpYieldControl (DhcpSb
);
742 gBS
->RestoreTPL (OldTpl
);
748 Starts the DHCP configuration process.
750 The Start() function starts the DHCP configuration process. This function can
751 be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or
752 Dhcp4InitReboot state.
753 If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol
754 driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the
755 Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.
756 If the process aborts, either by the user or by some unexpected network error,
757 the state is restored to the Dhcp4Init state. The Start() function can be called
758 again to restart the process.
759 Refer to RFC 2131 for precise state transitions during this process. At the
760 time when each event occurs in this process, the callback function that was set
761 by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this
762 opportunity to control the process.
764 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
765 @param CompletionEvent If not NULL, indicates the event that will be signaled when the
766 EFI DHCPv4 Protocol driver is transferred into the
767 Dhcp4Bound state or when the DHCP process is aborted.
768 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
769 check the completion status. If NULL,
770 EFI_DHCP4_PROTOCOL.Start() will wait until the driver
771 is transferred into the Dhcp4Bound state or the process fails.
773 @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed
774 when CompletionEvent is NULL.
775 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
776 state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.
777 @retval EFI_INVALID_PARAMETER This is NULL.
778 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
779 @retval EFI_TIMEOUT The DHCP configuration process failed because no response was
780 received from the server within the specified timeout value.
781 @retval EFI_ABORTED The user aborted the DHCP process.
782 @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the
784 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
790 IN EFI_DHCP4_PROTOCOL
*This
,
791 IN EFI_EVENT CompletionEvent OPTIONAL
794 DHCP_PROTOCOL
*Instance
;
795 DHCP_SERVICE
*DhcpSb
;
800 // First validate the parameters
803 return EFI_INVALID_PARAMETER
;
806 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
808 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
809 return EFI_INVALID_PARAMETER
;
812 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
813 DhcpSb
= Instance
->Service
;
815 if (DhcpSb
->DhcpState
== Dhcp4Stopped
) {
816 Status
= EFI_NOT_STARTED
;
820 if ((DhcpSb
->DhcpState
!= Dhcp4Init
) && (DhcpSb
->DhcpState
!= Dhcp4InitReboot
)) {
821 Status
= EFI_ALREADY_STARTED
;
825 DhcpSb
->IoStatus
= EFI_ALREADY_STARTED
;
827 if (EFI_ERROR (Status
= DhcpInitRequest (DhcpSb
))) {
832 // Start/Restart the receiving.
834 Status
= UdpIoRecvDatagram (DhcpSb
->UdpIo
, DhcpInput
, DhcpSb
, 0);
836 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
840 Instance
->CompletionEvent
= CompletionEvent
;
843 // Restore the TPL now, don't call poll function at TPL_CALLBACK.
845 gBS
->RestoreTPL (OldTpl
);
847 if (CompletionEvent
== NULL
) {
848 while (DhcpSb
->IoStatus
== EFI_ALREADY_STARTED
) {
849 DhcpSb
->UdpIo
->Udp
->Poll (DhcpSb
->UdpIo
->Udp
);
852 return DhcpSb
->IoStatus
;
858 gBS
->RestoreTPL (OldTpl
);
864 Extends the lease time by sending a request packet.
866 The RenewRebind() function is used to manually extend the lease time when the
867 EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has
868 not expired yet. This function will send a request packet to the previously
869 found server (or to any server when RebindRequest is TRUE) and transfer the
870 state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is
871 TRUE). When a response is received, the state is returned to Dhcp4Bound.
872 If no response is received before the try count is exceeded (the RequestTryCount
873 field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that
874 was issued by the previous server expires, the driver will return to the Dhcp4Bound
875 state and the previous configuration is restored. The outgoing and incoming packets
876 can be captured by the EFI_DHCP4_CALLBACK function.
878 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
879 @param RebindRequest If TRUE, this function broadcasts the request packets and enters
880 the Dhcp4Rebinding state. Otherwise, it sends a unicast
881 request packet and enters the Dhcp4Renewing state.
882 @param CompletionEvent If not NULL, this event is signaled when the renew/rebind phase
883 completes or some error occurs.
884 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
885 check the completion status. If NULL,
886 EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait
887 until the DHCP process finishes.
889 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the
890 Dhcp4Renewing state or is back to the Dhcp4Bound state.
891 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
892 state. EFI_DHCP4_PROTOCOL.Configure() needs to
894 @retval EFI_INVALID_PARAMETER This is NULL.
895 @retval EFI_TIMEOUT There was no response from the server when the try count was
897 @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.
898 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
903 EfiDhcp4RenewRebind (
904 IN EFI_DHCP4_PROTOCOL
*This
,
905 IN BOOLEAN RebindRequest
,
906 IN EFI_EVENT CompletionEvent OPTIONAL
909 DHCP_PROTOCOL
*Instance
;
910 DHCP_SERVICE
*DhcpSb
;
915 // First validate the parameters
918 return EFI_INVALID_PARAMETER
;
921 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
923 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
924 return EFI_INVALID_PARAMETER
;
927 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
928 DhcpSb
= Instance
->Service
;
930 if (DhcpSb
->DhcpState
== Dhcp4Stopped
) {
931 Status
= EFI_NOT_STARTED
;
935 if (DhcpSb
->DhcpState
!= Dhcp4Bound
) {
936 Status
= EFI_ACCESS_DENIED
;
940 if (DHCP_IS_BOOTP (DhcpSb
->Para
)) {
945 // Transit the states then send a extra DHCP request
947 if (!RebindRequest
) {
948 DhcpSetState (DhcpSb
, Dhcp4Renewing
, FALSE
);
950 DhcpSetState (DhcpSb
, Dhcp4Rebinding
, FALSE
);
953 Status
= DhcpSendMessage (
958 (UINT8
*) "Extra renew/rebind by the application"
961 if (EFI_ERROR (Status
)) {
962 DhcpSetState (DhcpSb
, Dhcp4Bound
, FALSE
);
966 DhcpSb
->ExtraRefresh
= TRUE
;
967 DhcpSb
->IoStatus
= EFI_ALREADY_STARTED
;
968 Instance
->RenewRebindEvent
= CompletionEvent
;
970 gBS
->RestoreTPL (OldTpl
);
972 if (CompletionEvent
== NULL
) {
973 while (DhcpSb
->IoStatus
== EFI_ALREADY_STARTED
) {
974 DhcpSb
->UdpIo
->Udp
->Poll (DhcpSb
->UdpIo
->Udp
);
977 return DhcpSb
->IoStatus
;
983 gBS
->RestoreTPL (OldTpl
);
989 Releases the current address configuration.
991 The Release() function releases the current configured IP address by doing either
993 * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the
995 * Setting the previously assigned IP address that was provided with the
996 EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in
997 Dhcp4InitReboot state
998 After a successful call to this function, the EFI DHCPv4 Protocol driver returns
999 to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.
1001 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
1003 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.
1004 @retval EFI_INVALID_PARAMETER This is NULL.
1005 @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.
1006 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
1012 IN EFI_DHCP4_PROTOCOL
*This
1015 DHCP_PROTOCOL
*Instance
;
1016 DHCP_SERVICE
*DhcpSb
;
1021 // First validate the parameters
1024 return EFI_INVALID_PARAMETER
;
1027 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
1029 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
1030 return EFI_INVALID_PARAMETER
;
1033 Status
= EFI_SUCCESS
;
1034 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1035 DhcpSb
= Instance
->Service
;
1037 if ((DhcpSb
->DhcpState
!= Dhcp4InitReboot
) && (DhcpSb
->DhcpState
!= Dhcp4Bound
)) {
1038 Status
= EFI_ACCESS_DENIED
;
1042 if (!DHCP_IS_BOOTP (DhcpSb
->Para
) && (DhcpSb
->DhcpState
== Dhcp4Bound
)) {
1043 Status
= DhcpSendMessage (
1051 if (EFI_ERROR (Status
)) {
1052 Status
= EFI_DEVICE_ERROR
;
1057 DhcpCleanLease (DhcpSb
);
1060 gBS
->RestoreTPL (OldTpl
);
1066 Stops the current address configuration.
1068 The Stop() function is used to stop the DHCP configuration process. After this
1069 function is called successfully, the EFI DHCPv4 Protocol driver is transferred
1070 into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called
1071 before DHCP configuration process can be started again. This function can be
1072 called when the EFI DHCPv4 Protocol driver is in any state.
1074 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
1076 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.
1077 @retval EFI_INVALID_PARAMETER This is NULL.
1083 IN EFI_DHCP4_PROTOCOL
*This
1086 DHCP_PROTOCOL
*Instance
;
1087 DHCP_SERVICE
*DhcpSb
;
1091 // First validate the parameters
1094 return EFI_INVALID_PARAMETER
;
1097 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
1099 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
1100 return EFI_INVALID_PARAMETER
;
1103 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1104 DhcpSb
= Instance
->Service
;
1106 DhcpCleanLease (DhcpSb
);
1108 DhcpSb
->DhcpState
= Dhcp4Stopped
;
1109 DhcpSb
->ServiceState
= DHCP_UNCONFIGED
;
1111 gBS
->RestoreTPL (OldTpl
);
1117 Builds a DHCP packet, given the options to be appended or deleted or replaced.
1119 The Build() function is used to assemble a new packet from the original packet
1120 by replacing or deleting existing options or appending new options. This function
1121 does not change any state of the EFI DHCPv4 Protocol driver and can be used at
1124 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
1125 @param SeedPacket Initial packet to be used as a base for building new packet.
1126 @param DeleteCount Number of opcodes in the DeleteList.
1127 @param DeleteList List of opcodes to be deleted from the seed packet.
1128 Ignored if DeleteCount is zero.
1129 @param AppendCount Number of entries in the OptionList.
1130 @param AppendList Pointer to a DHCP option list to be appended to SeedPacket.
1131 If SeedPacket also contains options in this list, they are
1132 replaced by new options (except pad option). Ignored if
1133 AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION
1134 @param NewPacket Pointer to storage for the pointer to the new allocated packet.
1135 Use the EFI Boot Service FreePool() on the resulting pointer
1136 when done with the packet.
1138 @retval EFI_SUCCESS The new packet was built.
1139 @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.
1140 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
1146 IN EFI_DHCP4_PROTOCOL
*This
,
1147 IN EFI_DHCP4_PACKET
*SeedPacket
,
1148 IN UINT32 DeleteCount
,
1149 IN UINT8
*DeleteList OPTIONAL
,
1150 IN UINT32 AppendCount
,
1151 IN EFI_DHCP4_PACKET_OPTION
*AppendList
[] OPTIONAL
,
1152 OUT EFI_DHCP4_PACKET
**NewPacket
1156 // First validate the parameters
1158 if ((This
== NULL
) || (NewPacket
== NULL
)) {
1159 return EFI_INVALID_PARAMETER
;
1162 if ((SeedPacket
== NULL
) || (SeedPacket
->Dhcp4
.Magik
!= DHCP_OPTION_MAGIC
) ||
1163 EFI_ERROR (DhcpValidateOptions (SeedPacket
, NULL
))) {
1165 return EFI_INVALID_PARAMETER
;
1168 if (((DeleteCount
== 0) && (AppendCount
== 0)) ||
1169 ((DeleteCount
!= 0) && (DeleteList
== NULL
)) ||
1170 ((AppendCount
!= 0) && (AppendList
== NULL
))) {
1172 return EFI_INVALID_PARAMETER
;
1186 Callback by UdpIoCreatePort() when creating UdpIo for this Dhcp4 instance.
1188 @param UdpIo The UdpIo being created.
1189 @param Context Dhcp4 instance.
1191 @retval EFI_SUCCESS UdpIo is configured successfully.
1192 @retval other Other error occurs.
1195 Dhcp4InstanceConfigUdpIo (
1196 IN UDP_IO_PORT
*UdpIo
,
1200 DHCP_PROTOCOL
*Instance
;
1201 DHCP_SERVICE
*DhcpSb
;
1202 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
*Token
;
1203 EFI_UDP4_CONFIG_DATA UdpConfigData
;
1206 Instance
= (DHCP_PROTOCOL
*) Context
;
1207 DhcpSb
= Instance
->Service
;
1208 Token
= Instance
->Token
;
1210 ZeroMem (&UdpConfigData
, sizeof (EFI_UDP4_CONFIG_DATA
));
1212 UdpConfigData
.AcceptBroadcast
= TRUE
;
1213 UdpConfigData
.AllowDuplicatePort
= TRUE
;
1214 UdpConfigData
.TimeToLive
= 64;
1215 UdpConfigData
.DoNotFragment
= TRUE
;
1217 Ip
= HTONL (DhcpSb
->ClientAddr
);
1218 CopyMem (&UdpConfigData
.StationAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
1220 Ip
= HTONL (DhcpSb
->Netmask
);
1221 CopyMem (&UdpConfigData
.SubnetMask
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
1223 if ((Token
->ListenPointCount
== 0) || (Token
->ListenPoints
[0].ListenPort
== 0)) {
1224 UdpConfigData
.StationPort
= DHCP_CLIENT_PORT
;
1226 UdpConfigData
.StationPort
= Token
->ListenPoints
[0].ListenPort
;
1229 return UdpIo
->Udp
->Configure (UdpIo
->Udp
, &UdpConfigData
);
1233 Create UdpIo for this Dhcp4 instance.
1235 @param Instance The Dhcp4 instance.
1237 @retval EFI_SUCCESS UdpIo is created successfully.
1238 @retval EFI_OUT_OF_RESOURCES Fails to create UdpIo because of limited
1239 resources or configuration failure.
1242 Dhcp4InstanceCreateUdpIo (
1243 IN OUT DHCP_PROTOCOL
*Instance
1246 DHCP_SERVICE
*DhcpSb
;
1248 ASSERT (Instance
->Token
!= NULL
);
1250 DhcpSb
= Instance
->Service
;
1251 Instance
->UdpIo
= UdpIoCreatePort (DhcpSb
->Controller
, DhcpSb
->Image
, Dhcp4InstanceConfigUdpIo
, Instance
);
1252 if (Instance
->UdpIo
== NULL
) {
1253 return EFI_OUT_OF_RESOURCES
;
1260 Callback of Dhcp packet. Does nothing.
1262 @param Arg The context.
1274 Callback of UdpIoRecvDatagram() that handles a Dhcp4 packet.
1276 Only BOOTP responses will be handled that correspond to the Xid of the request
1277 sent out. The packet will be queued to the response queue.
1279 @param UdpPacket The Dhcp4 packet.
1280 @param Points Udp4 address pair.
1281 @param IoStatus Status of the input.
1282 @param Context Extra info for the input.
1291 EFI_STATUS IoStatus
,
1295 DHCP_PROTOCOL
*Instance
;
1296 DHCP_SERVICE
*DhcpSb
;
1297 EFI_DHCP4_HEADER
*Head
;
1299 EFI_DHCP4_PACKET
*Packet
;
1300 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
*Token
;
1305 Instance
= (DHCP_PROTOCOL
*) Context
;
1306 Token
= Instance
->Token
;
1307 DhcpSb
= Instance
->Service
;
1310 // Don't restart receive if error occurs or DHCP is destroyed.
1312 if (EFI_ERROR (IoStatus
)) {
1316 ASSERT (UdpPacket
!= NULL
);
1319 // Validate the packet received
1321 if (UdpPacket
->TotalSize
< sizeof (EFI_DHCP4_HEADER
)) {
1326 // Copy the DHCP message to a continuous memory block, make the buffer size
1327 // of the EFI_DHCP4_PACKET a multiple of 4-byte.
1329 Len
= NET_ROUNDUP (sizeof (EFI_DHCP4_PACKET
) + UdpPacket
->TotalSize
- sizeof (EFI_DHCP4_HEADER
), 4);
1330 Wrap
= NetbufAlloc (Len
);
1336 Packet
= (EFI_DHCP4_PACKET
*) NetbufAllocSpace (Wrap
, Len
, NET_BUF_TAIL
);
1338 Head
= &Packet
->Dhcp4
.Header
;
1339 Packet
->Length
= NetbufCopy (UdpPacket
, 0, UdpPacket
->TotalSize
, (UINT8
*) Head
);
1341 if (Packet
->Length
!= UdpPacket
->TotalSize
) {
1346 // Is this packet the answer to our packet?
1348 if ((Head
->OpCode
!= BOOTP_REPLY
) ||
1349 (Head
->Xid
!= Token
->Packet
->Dhcp4
.Header
.Xid
) ||
1350 (CompareMem (DhcpSb
->ClientAddressSendOut
, Head
->ClientHwAddr
, Head
->HwAddrLen
) != 0)) {
1355 // Validate the options and retrieve the interested options
1357 if ((Packet
->Length
> sizeof (EFI_DHCP4_HEADER
) + sizeof (UINT32
)) &&
1358 (Packet
->Dhcp4
.Magik
== DHCP_OPTION_MAGIC
) &&
1359 EFI_ERROR (DhcpValidateOptions (Packet
, NULL
))) {
1365 // Keep this packet in the ResponseQueue.
1368 NetbufQueAppend (&Instance
->ResponseQueue
, Wrap
);
1372 NetbufFree (UdpPacket
);
1378 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, PxeDhcpInput
, Instance
, 0);
1379 if (EFI_ERROR (Status
)) {
1380 PxeDhcpDone (Instance
);
1385 Complete a Dhcp4 transaction and signal the upper layer.
1387 @param Instance Dhcp4 instance.
1394 IN DHCP_PROTOCOL
*Instance
1397 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
*Token
;
1399 Token
= Instance
->Token
;
1401 Token
->ResponseCount
= Instance
->ResponseQueue
.BufNum
;
1402 if (Token
->ResponseCount
!= 0) {
1403 Token
->ResponseList
= (EFI_DHCP4_PACKET
*) AllocatePool (Instance
->ResponseQueue
.BufSize
);
1404 if (Token
->ResponseList
== NULL
) {
1405 Token
->Status
= EFI_OUT_OF_RESOURCES
;
1410 // Copy the received DHCP responses.
1412 NetbufQueCopy (&Instance
->ResponseQueue
, 0, Instance
->ResponseQueue
.BufSize
, (UINT8
*) Token
->ResponseList
);
1413 Token
->Status
= EFI_SUCCESS
;
1415 Token
->ResponseList
= NULL
;
1416 Token
->Status
= EFI_TIMEOUT
;
1421 // Clean up the resources dedicated for this transmit receive transaction.
1423 NetbufQueFlush (&Instance
->ResponseQueue
);
1424 UdpIoCleanPort (Instance
->UdpIo
);
1425 UdpIoFreePort (Instance
->UdpIo
);
1426 Instance
->UdpIo
= NULL
;
1427 Instance
->Token
= NULL
;
1429 if (Token
->CompletionEvent
!= NULL
) {
1430 gBS
->SignalEvent (Token
->CompletionEvent
);
1436 Transmits a DHCP formatted packet and optionally waits for responses.
1438 The TransmitReceive() function is used to transmit a DHCP packet and optionally
1439 wait for the response from servers. This function does not change the state of
1440 the EFI DHCPv4 Protocol driver and thus can be used at any time.
1442 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
1443 @param Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.
1445 @retval EFI_SUCCESS The packet was successfully queued for transmission.
1446 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
1447 @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call
1448 this function after collection process completes.
1449 @retval EFI_NO_MAPPING The default station address is not available yet.
1450 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1451 @retval Others Some other unexpected error occurred.
1456 EfiDhcp4TransmitReceive (
1457 IN EFI_DHCP4_PROTOCOL
*This
,
1458 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
*Token
1461 DHCP_PROTOCOL
*Instance
;
1466 UDP_POINTS EndPoint
;
1468 DHCP_SERVICE
*DhcpSb
;
1470 IP4_ADDR SubnetMask
;
1472 if ((This
== NULL
) || (Token
== NULL
) || (Token
->Packet
== NULL
)) {
1473 return EFI_INVALID_PARAMETER
;
1476 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
1477 DhcpSb
= Instance
->Service
;
1479 if (Instance
->Token
!= NULL
) {
1481 // The previous call to TransmitReceive is not finished.
1483 return EFI_NOT_READY
;
1486 if ((Token
->Packet
->Dhcp4
.Magik
!= DHCP_OPTION_MAGIC
) ||
1487 (NTOHL (Token
->Packet
->Dhcp4
.Header
.Xid
) == Instance
->Service
->Xid
) ||
1488 (Token
->TimeoutValue
== 0) ||
1489 ((Token
->ListenPointCount
!= 0) && (Token
->ListenPoints
== NULL
)) ||
1490 EFI_ERROR (DhcpValidateOptions (Token
->Packet
, NULL
)) ||
1491 EFI_IP4_EQUAL (&Token
->RemoteAddress
, &mZeroIp4Addr
)
1494 // The DHCP packet isn't well-formed, the Transaction ID is already used,
1495 // the timeout value is zero, the ListenPoint is invalid, or the
1496 // RemoteAddress is zero.
1498 return EFI_INVALID_PARAMETER
;
1501 if (DhcpSb
->ClientAddr
== 0) {
1503 return EFI_NO_MAPPING
;
1506 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1509 // Save the token and the timeout value.
1511 Instance
->Token
= Token
;
1512 Instance
->Timeout
= Token
->TimeoutValue
;
1515 // Create a UDP IO for this transmit receive transaction.
1517 Status
= Dhcp4InstanceCreateUdpIo (Instance
);
1518 if (EFI_ERROR (Status
)) {
1523 // Save the Client Address is sent out
1526 &DhcpSb
->ClientAddressSendOut
[0],
1527 &Token
->Packet
->Dhcp4
.Header
.ClientHwAddr
[0],
1528 Token
->Packet
->Dhcp4
.Header
.HwAddrLen
1532 // Wrap the DHCP packet into a net buffer.
1534 Frag
.Bulk
= (UINT8
*) &Token
->Packet
->Dhcp4
;
1535 Frag
.Len
= Token
->Packet
->Length
;
1536 Wrap
= NetbufFromExt (&Frag
, 1, 0, 0, DhcpDummyExtFree
, NULL
);
1538 Status
= EFI_OUT_OF_RESOURCES
;
1543 // Set the local address and local port.
1545 EndPoint
.LocalAddr
= 0;
1546 EndPoint
.LocalPort
= 0;
1549 // Set the destination address and destination port.
1551 CopyMem (&Ip
, &Token
->RemoteAddress
, sizeof (EFI_IPv4_ADDRESS
));
1552 EndPoint
.RemoteAddr
= NTOHL (Ip
);
1554 if (Token
->RemotePort
== 0) {
1555 EndPoint
.RemotePort
= DHCP_SERVER_PORT
;
1557 EndPoint
.RemotePort
= Token
->RemotePort
;
1563 SubnetMask
= DhcpSb
->Netmask
;
1565 if (!IP4_NET_EQUAL (DhcpSb
->ClientAddr
, EndPoint
.RemoteAddr
, SubnetMask
)) {
1566 CopyMem (&Gateway
, &Token
->GatewayAddress
, sizeof (EFI_IPv4_ADDRESS
));
1567 Gateway
= NTOHL (Gateway
);
1571 // Transmit the DHCP packet.
1573 Status
= UdpIoSendDatagram (Instance
->UdpIo
, Wrap
, &EndPoint
, Gateway
, DhcpOnPacketSent
, NULL
);
1574 if (EFI_ERROR (Status
)) {
1580 // Start to receive the DHCP response.
1582 Status
= UdpIoRecvDatagram (Instance
->UdpIo
, PxeDhcpInput
, Instance
, 0);
1583 if (EFI_ERROR (Status
)) {
1589 if (EFI_ERROR (Status
) && (Instance
->UdpIo
!= NULL
)) {
1590 UdpIoCleanPort (Instance
->UdpIo
);
1591 UdpIoFreePort (Instance
->UdpIo
);
1592 Instance
->UdpIo
= NULL
;
1593 Instance
->Token
= NULL
;
1596 gBS
->RestoreTPL (OldTpl
);
1598 if (!EFI_ERROR (Status
) && (Token
->CompletionEvent
== NULL
)) {
1600 // Keep polling until timeout if no error happens and the CompletionEvent
1603 while (Instance
->Timeout
!= 0) {
1604 Instance
->UdpIo
->Udp
->Poll (Instance
->UdpIo
->Udp
);
1613 Callback function for DhcpIterateOptions. This callback sets the
1614 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point
1615 the individual DHCP option in the packet.
1617 @param Tag The DHCP option type
1618 @param Len Length of the DHCP option data
1619 @param Data The DHCP option data
1620 @param Context The context, to pass several parameters in.
1622 @retval EFI_SUCCESS It always returns EFI_SUCCESS
1626 Dhcp4ParseCheckOption (
1633 DHCP_PARSE_CONTEXT
*Parse
;
1635 Parse
= (DHCP_PARSE_CONTEXT
*) Context
;
1638 if (Parse
->Index
<= Parse
->OptionCount
) {
1640 // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for
1641 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only
1642 // pass in the point to option data.
1644 Parse
->Option
[Parse
->Index
- 1] = _CR (Data
, EFI_DHCP4_PACKET_OPTION
, Data
);
1652 Parses the packed DHCP option data.
1654 The Parse() function is used to retrieve the option list from a DHCP packet.
1655 If *OptionCount isn’t zero, and there is enough space for all the DHCP options
1656 in the Packet, each element of PacketOptionList is set to point to somewhere in
1657 the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,
1658 the caller should reassemble the parsed DHCP options to get the finial result.
1659 If *OptionCount is zero or there isn’t enough space for all of them, the number
1660 of DHCP options in the Packet is returned in OptionCount.
1662 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
1663 @param Packet Pointer to packet to be parsed.
1664 @param OptionCount On input, the number of entries in the PacketOptionList.
1665 On output, the number of entries that were written into the
1667 @param PacketOptionList List of packet option entries to be filled in. End option or pad
1668 options are not included.
1670 @retval EFI_SUCCESS The packet was successfully parsed.
1671 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
1672 @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:
1673 1) *OptionCount is smaller than the number of options that
1674 were found in the Packet.
1675 2) PacketOptionList is NULL.
1681 IN EFI_DHCP4_PROTOCOL
*This
,
1682 IN EFI_DHCP4_PACKET
*Packet
,
1683 IN OUT UINT32
*OptionCount
,
1684 OUT EFI_DHCP4_PACKET_OPTION
*PacketOptionList
[] OPTIONAL
1687 DHCP_PARSE_CONTEXT Context
;
1691 // First validate the parameters
1693 if ((This
== NULL
) || (Packet
== NULL
) || (OptionCount
== NULL
)) {
1694 return EFI_INVALID_PARAMETER
;
1697 if ((Packet
->Size
< Packet
->Length
+ 2 * sizeof (UINT32
)) ||
1698 (Packet
->Dhcp4
.Magik
!= DHCP_OPTION_MAGIC
) ||
1699 EFI_ERROR (DhcpValidateOptions (Packet
, NULL
))) {
1701 return EFI_INVALID_PARAMETER
;
1704 if ((*OptionCount
!= 0) && (PacketOptionList
== NULL
)) {
1705 return EFI_BUFFER_TOO_SMALL
;
1708 ZeroMem (PacketOptionList
, *OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
1710 Context
.Option
= PacketOptionList
;
1711 Context
.OptionCount
= *OptionCount
;
1714 Status
= DhcpIterateOptions (Packet
, Dhcp4ParseCheckOption
, &Context
);
1716 if (EFI_ERROR (Status
)) {
1720 *OptionCount
= Context
.Index
;
1722 if (Context
.Index
> Context
.OptionCount
) {
1723 return EFI_BUFFER_TOO_SMALL
;