]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Impl.c
1 /** @file
2 This file implement the EFI_DHCP4_PROTOCOL interface.
3
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
6
7 **/
8
9
10 #include "Dhcp4Impl.h"
11
12 /**
13 Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.
14
15 The GetModeData() function returns the current operating mode and cached data
16 packet for the EFI DHCPv4 Protocol driver.
17
18 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
19 @param[out] Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.
20
21 @retval EFI_SUCCESS The mode data was returned.
22 @retval EFI_INVALID_PARAMETER This is NULL.
23
24 **/
25 EFI_STATUS
26 EFIAPI
27 EfiDhcp4GetModeData (
28 IN EFI_DHCP4_PROTOCOL *This,
29 OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData
30 );
31
32 /**
33 Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.
34
35 The Configure() function is used to initialize, change, or reset the operational
36 settings of the EFI DHCPv4 Protocol driver for the communication device on which
37 the EFI DHCPv4 Service Binding Protocol is installed. This function can be
38 successfully called only if both of the following are true:
39 * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,
40 Dhcp4InitReboot, or Dhcp4Bound states.
41 * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI
42 DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4
43 Protocol driver.
44 When this driver is in the Dhcp4Stopped state, it can transfer into one of the
45 following two possible initial states:
46 * Dhcp4Init
47 * Dhcp4InitReboot
48 The driver can transfer into these states by calling Configure() with a non-NULL
49 Dhcp4CfgData. The driver will transfer into the appropriate state based on the
50 supplied client network address in the ClientAddress parameter and DHCP options
51 in the OptionList parameter as described in RFC 2131.
52 When Configure() is called successfully while Dhcp4CfgData is set to NULL, the
53 default configuring data will be reset in the EFI DHCPv4 Protocol driver and
54 the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance
55 wants to make it possible for another instance to configure the EFI DHCPv4 Protocol
56 driver, it must call this function with Dhcp4CfgData set to NULL.
57
58 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
59 @param[in] Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.
60
61 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or
62 Dhcp4InitReboot state, if the original state of this driver
63 was Dhcp4Stopped and the value of Dhcp4CfgData was
64 not NULL. Otherwise, the state was left unchanged.
65 @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the
66 Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;
67 Or onother instance of this EFI DHCPv4 Protocol driver is already
68 in a valid configured state.
69 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
70 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
71 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
72
73 **/
74 EFI_STATUS
75 EFIAPI
76 EfiDhcp4Configure (
77 IN EFI_DHCP4_PROTOCOL *This,
78 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL
79 );
80
81 /**
82 Starts the DHCP configuration process.
83
84 The Start() function starts the DHCP configuration process. This function can
85 be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or
86 Dhcp4InitReboot state.
87 If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol
88 driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the
89 Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.
90 If the process aborts, either by the user or by some unexpected network error,
91 the state is restored to the Dhcp4Init state. The Start() function can be called
92 again to restart the process.
93 Refer to RFC 2131 for precise state transitions during this process. At the
94 time when each event occurs in this process, the callback function that was set
95 by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this
96 opportunity to control the process.
97
98 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
99 @param[in] CompletionEvent If not NULL, indicates the event that will be signaled when the
100 EFI DHCPv4 Protocol driver is transferred into the
101 Dhcp4Bound state or when the DHCP process is aborted.
102 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
103 check the completion status. If NULL,
104 EFI_DHCP4_PROTOCOL.Start() will wait until the driver
105 is transferred into the Dhcp4Bound state or the process fails.
106
107 @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed
108 when CompletionEvent is NULL.
109 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
110 state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.
111 @retval EFI_INVALID_PARAMETER This is NULL.
112 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
113 @retval EFI_TIMEOUT The DHCP configuration process failed because no response was
114 received from the server within the specified timeout value.
115 @retval EFI_ABORTED The user aborted the DHCP process.
116 @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the
117 DHCP process.
118 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
119
120 **/
121 EFI_STATUS
122 EFIAPI
123 EfiDhcp4Start (
124 IN EFI_DHCP4_PROTOCOL *This,
125 IN EFI_EVENT CompletionEvent OPTIONAL
126 );
127
128 /**
129 Extends the lease time by sending a request packet.
130
131 The RenewRebind() function is used to manually extend the lease time when the
132 EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has
133 not expired yet. This function will send a request packet to the previously
134 found server (or to any server when RebindRequest is TRUE) and transfer the
135 state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is
136 TRUE). When a response is received, the state is returned to Dhcp4Bound.
137 If no response is received before the try count is exceeded (the RequestTryCount
138 field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that
139 was issued by the previous server expires, the driver will return to the Dhcp4Bound
140 state and the previous configuration is restored. The outgoing and incoming packets
141 can be captured by the EFI_DHCP4_CALLBACK function.
142
143 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
144 @param[in] RebindRequest If TRUE, this function broadcasts the request packets and enters
145 the Dhcp4Rebinding state. Otherwise, it sends a unicast
146 request packet and enters the Dhcp4Renewing state.
147 @param[in] CompletionEvent If not NULL, this event is signaled when the renew/rebind phase
148 completes or some error occurs.
149 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
150 check the completion status. If NULL,
151 EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait
152 until the DHCP process finishes.
153
154 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the
155 Dhcp4Renewing state or is back to the Dhcp4Bound state.
156 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
157 state. EFI_DHCP4_PROTOCOL.Configure() needs to
158 be called.
159 @retval EFI_INVALID_PARAMETER This is NULL.
160 @retval EFI_TIMEOUT There was no response from the server when the try count was
161 exceeded.
162 @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.
163 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
164
165 **/
166 EFI_STATUS
167 EFIAPI
168 EfiDhcp4RenewRebind (
169 IN EFI_DHCP4_PROTOCOL *This,
170 IN BOOLEAN RebindRequest,
171 IN EFI_EVENT CompletionEvent OPTIONAL
172 );
173
174 /**
175 Releases the current address configuration.
176
177 The Release() function releases the current configured IP address by doing either
178 of the following:
179 * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the
180 Dhcp4Bound state
181 * Setting the previously assigned IP address that was provided with the
182 EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in
183 Dhcp4InitReboot state
184 After a successful call to this function, the EFI DHCPv4 Protocol driver returns
185 to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.
186
187 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
188
189 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.
190 @retval EFI_INVALID_PARAMETER This is NULL.
191 @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.
192 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
193
194 **/
195 EFI_STATUS
196 EFIAPI
197 EfiDhcp4Release (
198 IN EFI_DHCP4_PROTOCOL *This
199 );
200
201 /**
202 Stops the current address configuration.
203
204 The Stop() function is used to stop the DHCP configuration process. After this
205 function is called successfully, the EFI DHCPv4 Protocol driver is transferred
206 into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called
207 before DHCP configuration process can be started again. This function can be
208 called when the EFI DHCPv4 Protocol driver is in any state.
209
210 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
211
212 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.
213 @retval EFI_INVALID_PARAMETER This is NULL.
214
215 **/
216 EFI_STATUS
217 EFIAPI
218 EfiDhcp4Stop (
219 IN EFI_DHCP4_PROTOCOL *This
220 );
221
222 /**
223 Builds a DHCP packet, given the options to be appended or deleted or replaced.
224
225 The Build() function is used to assemble a new packet from the original packet
226 by replacing or deleting existing options or appending new options. This function
227 does not change any state of the EFI DHCPv4 Protocol driver and can be used at
228 any time.
229
230 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
231 @param[in] SeedPacket Initial packet to be used as a base for building new packet.
232 @param[in] DeleteCount Number of opcodes in the DeleteList.
233 @param[in] DeleteList List of opcodes to be deleted from the seed packet.
234 Ignored if DeleteCount is zero.
235 @param[in] AppendCount Number of entries in the OptionList.
236 @param[in] AppendList Pointer to a DHCP option list to be appended to SeedPacket.
237 If SeedPacket also contains options in this list, they are
238 replaced by new options (except pad option). Ignored if
239 AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION
240 @param[out] NewPacket Pointer to storage for the pointer to the new allocated packet.
241 Use the EFI Boot Service FreePool() on the resulting pointer
242 when done with the packet.
243
244 @retval EFI_SUCCESS The new packet was built.
245 @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.
246 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
247
248 **/
249 EFI_STATUS
250 EFIAPI
251 EfiDhcp4Build (
252 IN EFI_DHCP4_PROTOCOL *This,
253 IN EFI_DHCP4_PACKET *SeedPacket,
254 IN UINT32 DeleteCount,
255 IN UINT8 *DeleteList OPTIONAL,
256 IN UINT32 AppendCount,
257 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
258 OUT EFI_DHCP4_PACKET **NewPacket
259 );
260
261 /**
262 Transmits a DHCP formatted packet and optionally waits for responses.
263
264 The TransmitReceive() function is used to transmit a DHCP packet and optionally
265 wait for the response from servers. This function does not change the state of
266 the EFI DHCPv4 Protocol driver and thus can be used at any time.
267
268 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
269 @param[in] Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.
270
271 @retval EFI_SUCCESS The packet was successfully queued for transmission.
272 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
273 @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call
274 this function after collection process completes.
275 @retval EFI_NO_MAPPING The default station address is not available yet.
276 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
277 @retval Others Some other unexpected error occurred.
278
279 **/
280 EFI_STATUS
281 EFIAPI
282 EfiDhcp4TransmitReceive (
283 IN EFI_DHCP4_PROTOCOL *This,
284 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token
285 );
286
287 /**
288 Parses the packed DHCP option data.
289
290 The Parse() function is used to retrieve the option list from a DHCP packet.
291 If *OptionCount isn't zero, and there is enough space for all the DHCP options
292 in the Packet, each element of PacketOptionList is set to point to somewhere in
293 the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,
294 the caller should reassemble the parsed DHCP options to get the finial result.
295 If *OptionCount is zero or there isn't enough space for all of them, the number
296 of DHCP options in the Packet is returned in OptionCount.
297
298 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
299 @param Packet Pointer to packet to be parsed.
300 @param OptionCount On input, the number of entries in the PacketOptionList.
301 On output, the number of entries that were written into the
302 PacketOptionList.
303 @param PacketOptionList List of packet option entries to be filled in. End option or pad
304 options are not included.
305
306 @retval EFI_SUCCESS The packet was successfully parsed.
307 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
308 @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:
309 1) *OptionCount is smaller than the number of options that
310 were found in the Packet.
311 2) PacketOptionList is NULL.
312
313 **/
314 EFI_STATUS
315 EFIAPI
316 EfiDhcp4Parse (
317 IN EFI_DHCP4_PROTOCOL *This,
318 IN EFI_DHCP4_PACKET *Packet,
319 IN OUT UINT32 *OptionCount,
320 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL
321 );
322
323 EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {
324 EfiDhcp4GetModeData,
325 EfiDhcp4Configure,
326 EfiDhcp4Start,
327 EfiDhcp4RenewRebind,
328 EfiDhcp4Release,
329 EfiDhcp4Stop,
330 EfiDhcp4Build,
331 EfiDhcp4TransmitReceive,
332 EfiDhcp4Parse
333 };
334
335 /**
336 Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver.
337
338 The GetModeData() function returns the current operating mode and cached data
339 packet for the EFI DHCPv4 Protocol driver.
340
341 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
342 @param[out] Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure.
343
344 @retval EFI_SUCCESS The mode data was returned.
345 @retval EFI_INVALID_PARAMETER This is NULL.
346
347 **/
348 EFI_STATUS
349 EFIAPI
350 EfiDhcp4GetModeData (
351 IN EFI_DHCP4_PROTOCOL *This,
352 OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData
353 )
354 {
355 DHCP_PROTOCOL *Instance;
356 DHCP_SERVICE *DhcpSb;
357 DHCP_PARAMETER *Para;
358 EFI_TPL OldTpl;
359 IP4_ADDR Ip;
360
361 //
362 // First validate the parameters.
363 //
364 if ((This == NULL) || (Dhcp4ModeData == NULL)) {
365 return EFI_INVALID_PARAMETER;
366 }
367
368 Instance = DHCP_INSTANCE_FROM_THIS (This);
369
370 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
371 DhcpSb = Instance->Service;
372
373 //
374 // Caller can use GetModeData to retrieve current DHCP states
375 // no matter whether it is the active child or not.
376 //
377 Dhcp4ModeData->State = (EFI_DHCP4_STATE) DhcpSb->DhcpState;
378 CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (Dhcp4ModeData->ConfigData));
379 CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (Dhcp4ModeData->ClientMacAddress));
380
381 Ip = HTONL (DhcpSb->ClientAddr);
382 CopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
383
384 Ip = HTONL (DhcpSb->Netmask);
385 CopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
386
387 Ip = HTONL (DhcpSb->ServerAddr);
388 CopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
389
390 Para = DhcpSb->Para;
391
392 if (Para != NULL) {
393 Ip = HTONL (Para->Router);
394 CopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
395 Dhcp4ModeData->LeaseTime = Para->Lease;
396 } else {
397 ZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));
398 Dhcp4ModeData->LeaseTime = 0xffffffff;
399 }
400
401 Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;
402
403 gBS->RestoreTPL (OldTpl);
404 return EFI_SUCCESS;
405 }
406
407
408 /**
409 Free the resource related to the configure parameters.
410 DHCP driver will make a copy of the user's configure
411 such as the time out value.
412
413 @param Config The DHCP configure data
414
415 **/
416 VOID
417 DhcpCleanConfigure (
418 IN OUT EFI_DHCP4_CONFIG_DATA *Config
419 )
420 {
421 UINT32 Index;
422
423 if (Config->DiscoverTimeout != NULL) {
424 FreePool (Config->DiscoverTimeout);
425 }
426
427 if (Config->RequestTimeout != NULL) {
428 FreePool (Config->RequestTimeout);
429 }
430
431 if (Config->OptionList != NULL) {
432 for (Index = 0; Index < Config->OptionCount; Index++) {
433 if (Config->OptionList[Index] != NULL) {
434 FreePool (Config->OptionList[Index]);
435 }
436 }
437
438 FreePool (Config->OptionList);
439 }
440
441 ZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));
442 }
443
444
445 /**
446 Allocate memory for configure parameter such as timeout value for Dst,
447 then copy the configure parameter from Src to Dst.
448
449 @param[out] Dst The destination DHCP configure data.
450 @param[in] Src The source DHCP configure data.
451
452 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
453 @retval EFI_SUCCESS The configure is copied.
454
455 **/
456 EFI_STATUS
457 DhcpCopyConfigure (
458 OUT EFI_DHCP4_CONFIG_DATA *Dst,
459 IN EFI_DHCP4_CONFIG_DATA *Src
460 )
461 {
462 EFI_DHCP4_PACKET_OPTION **DstOptions;
463 EFI_DHCP4_PACKET_OPTION **SrcOptions;
464 UINTN Len;
465 UINT32 Index;
466
467 CopyMem (Dst, Src, sizeof (*Dst));
468 Dst->DiscoverTimeout = NULL;
469 Dst->RequestTimeout = NULL;
470 Dst->OptionList = NULL;
471
472 //
473 // Allocate a memory then copy DiscoverTimeout to it
474 //
475 if (Src->DiscoverTimeout != NULL) {
476 Len = Src->DiscoverTryCount * sizeof (UINT32);
477 Dst->DiscoverTimeout = AllocatePool (Len);
478
479 if (Dst->DiscoverTimeout == NULL) {
480 return EFI_OUT_OF_RESOURCES;
481 }
482
483 for (Index = 0; Index < Src->DiscoverTryCount; Index++) {
484 Dst->DiscoverTimeout[Index] = MAX (Src->DiscoverTimeout[Index], 1);
485 }
486 }
487
488 //
489 // Allocate a memory then copy RequestTimeout to it
490 //
491 if (Src->RequestTimeout != NULL) {
492 Len = Src->RequestTryCount * sizeof (UINT32);
493 Dst->RequestTimeout = AllocatePool (Len);
494
495 if (Dst->RequestTimeout == NULL) {
496 goto ON_ERROR;
497 }
498
499 for (Index = 0; Index < Src->RequestTryCount; Index++) {
500 Dst->RequestTimeout[Index] = MAX (Src->RequestTimeout[Index], 1);
501 }
502 }
503
504 //
505 // Allocate an array of dhcp option point, then allocate memory
506 // for each option and copy the source option to it
507 //
508 if (Src->OptionList != NULL) {
509 Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);
510 Dst->OptionList = AllocateZeroPool (Len);
511
512 if (Dst->OptionList == NULL) {
513 goto ON_ERROR;
514 }
515
516 DstOptions = Dst->OptionList;
517 SrcOptions = Src->OptionList;
518
519 for (Index = 0; Index < Src->OptionCount; Index++) {
520 Len = sizeof (EFI_DHCP4_PACKET_OPTION) + MAX (SrcOptions[Index]->Length - 1, 0);
521
522 DstOptions[Index] = AllocatePool (Len);
523
524 if (DstOptions[Index] == NULL) {
525 goto ON_ERROR;
526 }
527
528 CopyMem (DstOptions[Index], SrcOptions[Index], Len);
529 }
530 }
531
532 return EFI_SUCCESS;
533
534 ON_ERROR:
535 DhcpCleanConfigure (Dst);
536 return EFI_OUT_OF_RESOURCES;
537 }
538
539
540 /**
541 Give up the control of the DHCP service to let other child
542 resume. Don't change the service's DHCP state and the Client
543 address and option list configure as required by RFC2131.
544
545 @param DhcpSb The DHCP service instance.
546
547 **/
548 VOID
549 DhcpYieldControl (
550 IN DHCP_SERVICE *DhcpSb
551 )
552 {
553 EFI_DHCP4_CONFIG_DATA *Config;
554
555 Config = &DhcpSb->ActiveConfig;
556
557 DhcpSb->ServiceState = DHCP_UNCONFIGED;
558 DhcpSb->ActiveChild = NULL;
559
560 if (Config->DiscoverTimeout != NULL) {
561 FreePool (Config->DiscoverTimeout);
562
563 Config->DiscoverTryCount = 0;
564 Config->DiscoverTimeout = NULL;
565 }
566
567 if (Config->RequestTimeout != NULL) {
568 FreePool (Config->RequestTimeout);
569
570 Config->RequestTryCount = 0;
571 Config->RequestTimeout = NULL;
572 }
573
574 Config->Dhcp4Callback = NULL;
575 Config->CallbackContext = NULL;
576 }
577
578
579 /**
580 Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver.
581
582 The Configure() function is used to initialize, change, or reset the operational
583 settings of the EFI DHCPv4 Protocol driver for the communication device on which
584 the EFI DHCPv4 Service Binding Protocol is installed. This function can be
585 successfully called only if both of the following are true:
586 * This instance of the EFI DHCPv4 Protocol driver is in the Dhcp4Stopped, Dhcp4Init,
587 Dhcp4InitReboot, or Dhcp4Bound states.
588 * No other EFI DHCPv4 Protocol driver instance that is controlled by this EFI
589 DHCPv4 Service Binding Protocol driver instance has configured this EFI DHCPv4
590 Protocol driver.
591 When this driver is in the Dhcp4Stopped state, it can transfer into one of the
592 following two possible initial states:
593 * Dhcp4Init
594 * Dhcp4InitReboot
595 The driver can transfer into these states by calling Configure() with a non-NULL
596 Dhcp4CfgData. The driver will transfer into the appropriate state based on the
597 supplied client network address in the ClientAddress parameter and DHCP options
598 in the OptionList parameter as described in RFC 2131.
599 When Configure() is called successfully while Dhcp4CfgData is set to NULL, the
600 default configuring data will be reset in the EFI DHCPv4 Protocol driver and
601 the state of the EFI DHCPv4 Protocol driver will not be changed. If one instance
602 wants to make it possible for another instance to configure the EFI DHCPv4 Protocol
603 driver, it must call this function with Dhcp4CfgData set to NULL.
604
605 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
606 @param[in] Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA.
607
608 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or
609 Dhcp4InitReboot state, if the original state of this driver
610 was Dhcp4Stopped and the value of Dhcp4CfgData was
611 not NULL. Otherwise, the state was left unchanged.
612 @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the
613 Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state;
614 Or onother instance of this EFI DHCPv4 Protocol driver is already
615 in a valid configured state.
616 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
617 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
618 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
619
620 **/
621 EFI_STATUS
622 EFIAPI
623 EfiDhcp4Configure (
624 IN EFI_DHCP4_PROTOCOL *This,
625 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL
626 )
627 {
628 EFI_DHCP4_CONFIG_DATA *Config;
629 DHCP_PROTOCOL *Instance;
630 DHCP_SERVICE *DhcpSb;
631 EFI_STATUS Status;
632 EFI_TPL OldTpl;
633 UINT32 Index;
634 IP4_ADDR Ip;
635
636 //
637 // First validate the parameters
638 //
639 if (This == NULL) {
640 return EFI_INVALID_PARAMETER;
641 }
642
643 if (Dhcp4CfgData != NULL) {
644 if ((Dhcp4CfgData->DiscoverTryCount != 0) && (Dhcp4CfgData->DiscoverTimeout == NULL)) {
645 return EFI_INVALID_PARAMETER;
646 }
647
648 if ((Dhcp4CfgData->RequestTryCount != 0) && (Dhcp4CfgData->RequestTimeout == NULL)) {
649 return EFI_INVALID_PARAMETER;
650 }
651
652 if ((Dhcp4CfgData->OptionCount != 0) && (Dhcp4CfgData->OptionList == NULL)) {
653 return EFI_INVALID_PARAMETER;
654 }
655
656 CopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));
657 if (IP4_IS_LOCAL_BROADCAST(NTOHL (Ip))) {
658 return EFI_INVALID_PARAMETER;
659 }
660 }
661
662 Instance = DHCP_INSTANCE_FROM_THIS (This);
663
664 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
665 return EFI_INVALID_PARAMETER;
666 }
667
668 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
669
670 DhcpSb = Instance->Service;
671 Config = &DhcpSb->ActiveConfig;
672
673 Status = EFI_ACCESS_DENIED;
674
675 if ((DhcpSb->DhcpState != Dhcp4Stopped) &&
676 (DhcpSb->DhcpState != Dhcp4Init) &&
677 (DhcpSb->DhcpState != Dhcp4InitReboot) &&
678 (DhcpSb->DhcpState != Dhcp4Bound)) {
679
680 goto ON_EXIT;
681 }
682
683 if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {
684 goto ON_EXIT;
685 }
686
687 if (Dhcp4CfgData != NULL) {
688 Status = EFI_OUT_OF_RESOURCES;
689 DhcpCleanConfigure (Config);
690
691 if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {
692 goto ON_EXIT;
693 }
694
695 DhcpSb->UserOptionLen = 0;
696
697 for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {
698 DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;
699 }
700
701 DhcpSb->ActiveChild = Instance;
702
703 if (DhcpSb->DhcpState == Dhcp4Stopped) {
704 DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);
705
706 if (DhcpSb->ClientAddr != 0) {
707 DhcpSb->DhcpState = Dhcp4InitReboot;
708 } else {
709 DhcpSb->DhcpState = Dhcp4Init;
710 }
711 }
712
713 DhcpSb->ServiceState = DHCP_CONFIGED;
714 Status = EFI_SUCCESS;
715
716 } else if (DhcpSb->ActiveChild == Instance) {
717 Status = EFI_SUCCESS;
718 DhcpYieldControl (DhcpSb);
719 }
720
721 ON_EXIT:
722 gBS->RestoreTPL (OldTpl);
723 return Status;
724 }
725
726
727 /**
728 Starts the DHCP configuration process.
729
730 The Start() function starts the DHCP configuration process. This function can
731 be called only when the EFI DHCPv4 Protocol driver is in the Dhcp4Init or
732 Dhcp4InitReboot state.
733 If the DHCP process completes successfully, the state of the EFI DHCPv4 Protocol
734 driver will be transferred through Dhcp4Selecting and Dhcp4Requesting to the
735 Dhcp4Bound state. The CompletionEvent will then be signaled if it is not NULL.
736 If the process aborts, either by the user or by some unexpected network error,
737 the state is restored to the Dhcp4Init state. The Start() function can be called
738 again to restart the process.
739 Refer to RFC 2131 for precise state transitions during this process. At the
740 time when each event occurs in this process, the callback function that was set
741 by EFI_DHCP4_PROTOCOL.Configure() will be called and the user can take this
742 opportunity to control the process.
743
744 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
745 @param[in] CompletionEvent If not NULL, indicates the event that will be signaled when the
746 EFI DHCPv4 Protocol driver is transferred into the
747 Dhcp4Bound state or when the DHCP process is aborted.
748 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
749 check the completion status. If NULL,
750 EFI_DHCP4_PROTOCOL.Start() will wait until the driver
751 is transferred into the Dhcp4Bound state or the process fails.
752
753 @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed
754 when CompletionEvent is NULL.
755 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
756 state. EFI_DHCP4_PROTOCOL. Configure() needs to be called.
757 @retval EFI_INVALID_PARAMETER This is NULL.
758 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
759 @retval EFI_TIMEOUT The DHCP configuration process failed because no response was
760 received from the server within the specified timeout value.
761 @retval EFI_ABORTED The user aborted the DHCP process.
762 @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the
763 DHCP process.
764 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
765 @retval EFI_NO_MEDIA There was a media error.
766
767 **/
768 EFI_STATUS
769 EFIAPI
770 EfiDhcp4Start (
771 IN EFI_DHCP4_PROTOCOL *This,
772 IN EFI_EVENT CompletionEvent OPTIONAL
773 )
774 {
775 DHCP_PROTOCOL *Instance;
776 DHCP_SERVICE *DhcpSb;
777 EFI_STATUS Status;
778 EFI_TPL OldTpl;
779 EFI_STATUS MediaStatus;
780
781 //
782 // First validate the parameters
783 //
784 if (This == NULL) {
785 return EFI_INVALID_PARAMETER;
786 }
787
788 Instance = DHCP_INSTANCE_FROM_THIS (This);
789
790 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
791 return EFI_INVALID_PARAMETER;
792 }
793
794 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
795 DhcpSb = Instance->Service;
796
797 if (DhcpSb->DhcpState == Dhcp4Stopped) {
798 Status = EFI_NOT_STARTED;
799 goto ON_ERROR;
800 }
801
802 if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {
803 Status = EFI_ALREADY_STARTED;
804 goto ON_ERROR;
805 }
806
807 //
808 // Check Media Satus.
809 //
810 MediaStatus = EFI_SUCCESS;
811 NetLibDetectMediaWaitTimeout (DhcpSb->Controller, DHCP_CHECK_MEDIA_WAITING_TIME, &MediaStatus);
812 if (MediaStatus != EFI_SUCCESS) {
813 Status = EFI_NO_MEDIA;
814 goto ON_ERROR;
815 }
816
817 DhcpSb->IoStatus = EFI_ALREADY_STARTED;
818
819 if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {
820 goto ON_ERROR;
821 }
822
823
824 Instance->CompletionEvent = CompletionEvent;
825
826 //
827 // Restore the TPL now, don't call poll function at TPL_CALLBACK.
828 //
829 gBS->RestoreTPL (OldTpl);
830
831 if (CompletionEvent == NULL) {
832 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
833 DhcpSb->UdpIo->Protocol.Udp4->Poll (DhcpSb->UdpIo->Protocol.Udp4);
834 }
835
836 return DhcpSb->IoStatus;
837 }
838
839 return EFI_SUCCESS;
840
841 ON_ERROR:
842 gBS->RestoreTPL (OldTpl);
843 return Status;
844 }
845
846
847 /**
848 Extends the lease time by sending a request packet.
849
850 The RenewRebind() function is used to manually extend the lease time when the
851 EFI DHCPv4 Protocol driver is in the Dhcp4Bound state and the lease time has
852 not expired yet. This function will send a request packet to the previously
853 found server (or to any server when RebindRequest is TRUE) and transfer the
854 state into the Dhcp4Renewing state (or Dhcp4Rebinding when RebindingRequest is
855 TRUE). When a response is received, the state is returned to Dhcp4Bound.
856 If no response is received before the try count is exceeded (the RequestTryCount
857 field that is specified in EFI_DHCP4_CONFIG_DATA) but before the lease time that
858 was issued by the previous server expires, the driver will return to the Dhcp4Bound
859 state and the previous configuration is restored. The outgoing and incoming packets
860 can be captured by the EFI_DHCP4_CALLBACK function.
861
862 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
863 @param[in] RebindRequest If TRUE, this function broadcasts the request packets and enters
864 the Dhcp4Rebinding state. Otherwise, it sends a unicast
865 request packet and enters the Dhcp4Renewing state.
866 @param[in] CompletionEvent If not NULL, this event is signaled when the renew/rebind phase
867 completes or some error occurs.
868 EFI_DHCP4_PROTOCOL.GetModeData() can be called to
869 check the completion status. If NULL,
870 EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait
871 until the DHCP process finishes.
872
873 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the
874 Dhcp4Renewing state or is back to the Dhcp4Bound state.
875 @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped
876 state. EFI_DHCP4_PROTOCOL.Configure() needs to
877 be called.
878 @retval EFI_INVALID_PARAMETER This is NULL.
879 @retval EFI_TIMEOUT There was no response from the server when the try count was
880 exceeded.
881 @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state.
882 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
883
884 **/
885 EFI_STATUS
886 EFIAPI
887 EfiDhcp4RenewRebind (
888 IN EFI_DHCP4_PROTOCOL *This,
889 IN BOOLEAN RebindRequest,
890 IN EFI_EVENT CompletionEvent OPTIONAL
891 )
892 {
893 DHCP_PROTOCOL *Instance;
894 DHCP_SERVICE *DhcpSb;
895 EFI_STATUS Status;
896 EFI_TPL OldTpl;
897
898 //
899 // First validate the parameters
900 //
901 if (This == NULL) {
902 return EFI_INVALID_PARAMETER;
903 }
904
905 Instance = DHCP_INSTANCE_FROM_THIS (This);
906
907 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
908 return EFI_INVALID_PARAMETER;
909 }
910
911 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
912 DhcpSb = Instance->Service;
913
914 if (DhcpSb->DhcpState == Dhcp4Stopped) {
915 Status = EFI_NOT_STARTED;
916 goto ON_EXIT;
917 }
918
919 if (DhcpSb->DhcpState != Dhcp4Bound) {
920 Status = EFI_ACCESS_DENIED;
921 goto ON_EXIT;
922 }
923
924 if (DHCP_IS_BOOTP (DhcpSb->Para)) {
925 Status = EFI_SUCCESS;
926 goto ON_EXIT;
927 }
928
929 //
930 // Transit the states then send a extra DHCP request
931 //
932 if (!RebindRequest) {
933 DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);
934 } else {
935 DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);
936 }
937
938 //
939 // Clear initial time to make sure that elapsed-time
940 // is set to 0 for first REQUEST in renewal process.
941 //
942 Instance->ElaspedTime = 0;
943
944 Status = DhcpSendMessage (
945 DhcpSb,
946 DhcpSb->Selected,
947 DhcpSb->Para,
948 DHCP_MSG_REQUEST,
949 (UINT8 *) "Extra renew/rebind by the application"
950 );
951
952 if (EFI_ERROR (Status)) {
953 DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);
954 goto ON_EXIT;
955 }
956
957 DhcpSb->ExtraRefresh = TRUE;
958 DhcpSb->IoStatus = EFI_ALREADY_STARTED;
959 Instance->RenewRebindEvent = CompletionEvent;
960
961 gBS->RestoreTPL (OldTpl);
962
963 if (CompletionEvent == NULL) {
964 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
965 DhcpSb->UdpIo->Protocol.Udp4->Poll (DhcpSb->UdpIo->Protocol.Udp4);
966
967 }
968
969 return DhcpSb->IoStatus;
970 }
971
972 return EFI_SUCCESS;
973
974 ON_EXIT:
975 gBS->RestoreTPL (OldTpl);
976 return Status;
977 }
978
979
980 /**
981 Releases the current address configuration.
982
983 The Release() function releases the current configured IP address by doing either
984 of the following:
985 * Sending a DHCPRELEASE packet when the EFI DHCPv4 Protocol driver is in the
986 Dhcp4Bound state
987 * Setting the previously assigned IP address that was provided with the
988 EFI_DHCP4_PROTOCOL.Configure() function to 0.0.0.0 when the driver is in
989 Dhcp4InitReboot state
990 After a successful call to this function, the EFI DHCPv4 Protocol driver returns
991 to the Dhcp4Init state and any subsequent incoming packets will be discarded silently.
992
993 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
994
995 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase.
996 @retval EFI_INVALID_PARAMETER This is NULL.
997 @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state.
998 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
999
1000 **/
1001 EFI_STATUS
1002 EFIAPI
1003 EfiDhcp4Release (
1004 IN EFI_DHCP4_PROTOCOL *This
1005 )
1006 {
1007 DHCP_PROTOCOL *Instance;
1008 DHCP_SERVICE *DhcpSb;
1009 EFI_STATUS Status;
1010 EFI_TPL OldTpl;
1011
1012 //
1013 // First validate the parameters
1014 //
1015 if (This == NULL) {
1016 return EFI_INVALID_PARAMETER;
1017 }
1018
1019 Instance = DHCP_INSTANCE_FROM_THIS (This);
1020
1021 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
1022 return EFI_INVALID_PARAMETER;
1023 }
1024
1025 Status = EFI_SUCCESS;
1026 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1027 DhcpSb = Instance->Service;
1028
1029 if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {
1030 Status = EFI_ACCESS_DENIED;
1031 goto ON_EXIT;
1032 }
1033
1034 if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {
1035 Status = DhcpSendMessage (
1036 DhcpSb,
1037 DhcpSb->Selected,
1038 DhcpSb->Para,
1039 DHCP_MSG_RELEASE,
1040 NULL
1041 );
1042
1043 if (EFI_ERROR (Status)) {
1044 Status = EFI_DEVICE_ERROR;
1045 goto ON_EXIT;
1046 }
1047 }
1048
1049 DhcpCleanLease (DhcpSb);
1050
1051 ON_EXIT:
1052 gBS->RestoreTPL (OldTpl);
1053 return Status;
1054 }
1055
1056
1057 /**
1058 Stops the current address configuration.
1059
1060 The Stop() function is used to stop the DHCP configuration process. After this
1061 function is called successfully, the EFI DHCPv4 Protocol driver is transferred
1062 into the Dhcp4Stopped state. EFI_DHCP4_PROTOCOL.Configure() needs to be called
1063 before DHCP configuration process can be started again. This function can be
1064 called when the EFI DHCPv4 Protocol driver is in any state.
1065
1066 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
1067
1068 @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase.
1069 @retval EFI_INVALID_PARAMETER This is NULL.
1070
1071 **/
1072 EFI_STATUS
1073 EFIAPI
1074 EfiDhcp4Stop (
1075 IN EFI_DHCP4_PROTOCOL *This
1076 )
1077 {
1078 DHCP_PROTOCOL *Instance;
1079 DHCP_SERVICE *DhcpSb;
1080 EFI_TPL OldTpl;
1081
1082 //
1083 // First validate the parameters
1084 //
1085 if (This == NULL) {
1086 return EFI_INVALID_PARAMETER;
1087 }
1088
1089 Instance = DHCP_INSTANCE_FROM_THIS (This);
1090
1091 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
1092 return EFI_INVALID_PARAMETER;
1093 }
1094
1095 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1096 DhcpSb = Instance->Service;
1097
1098 DhcpCleanLease (DhcpSb);
1099
1100 DhcpSb->DhcpState = Dhcp4Stopped;
1101 DhcpSb->ServiceState = DHCP_UNCONFIGED;
1102
1103 gBS->RestoreTPL (OldTpl);
1104 return EFI_SUCCESS;
1105 }
1106
1107
1108 /**
1109 Builds a DHCP packet, given the options to be appended or deleted or replaced.
1110
1111 The Build() function is used to assemble a new packet from the original packet
1112 by replacing or deleting existing options or appending new options. This function
1113 does not change any state of the EFI DHCPv4 Protocol driver and can be used at
1114 any time.
1115
1116 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
1117 @param[in] SeedPacket Initial packet to be used as a base for building new packet.
1118 @param[in] DeleteCount Number of opcodes in the DeleteList.
1119 @param[in] DeleteList List of opcodes to be deleted from the seed packet.
1120 Ignored if DeleteCount is zero.
1121 @param[in] AppendCount Number of entries in the OptionList.
1122 @param[in] AppendList Pointer to a DHCP option list to be appended to SeedPacket.
1123 If SeedPacket also contains options in this list, they are
1124 replaced by new options (except pad option). Ignored if
1125 AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION
1126 @param[out] NewPacket Pointer to storage for the pointer to the new allocated packet.
1127 Use the EFI Boot Service FreePool() on the resulting pointer
1128 when done with the packet.
1129
1130 @retval EFI_SUCCESS The new packet was built.
1131 @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated.
1132 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
1133
1134 **/
1135 EFI_STATUS
1136 EFIAPI
1137 EfiDhcp4Build (
1138 IN EFI_DHCP4_PROTOCOL *This,
1139 IN EFI_DHCP4_PACKET *SeedPacket,
1140 IN UINT32 DeleteCount,
1141 IN UINT8 *DeleteList OPTIONAL,
1142 IN UINT32 AppendCount,
1143 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
1144 OUT EFI_DHCP4_PACKET **NewPacket
1145 )
1146 {
1147 //
1148 // First validate the parameters
1149 //
1150 if ((This == NULL) || (NewPacket == NULL)) {
1151 return EFI_INVALID_PARAMETER;
1152 }
1153
1154 if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
1155 EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {
1156
1157 return EFI_INVALID_PARAMETER;
1158 }
1159
1160 if (((DeleteCount == 0) && (AppendCount == 0)) ||
1161 ((DeleteCount != 0) && (DeleteList == NULL)) ||
1162 ((AppendCount != 0) && (AppendList == NULL))) {
1163
1164 return EFI_INVALID_PARAMETER;
1165 }
1166
1167 return DhcpBuild (
1168 SeedPacket,
1169 DeleteCount,
1170 DeleteList,
1171 AppendCount,
1172 AppendList,
1173 NewPacket
1174 );
1175 }
1176
1177 /**
1178 Callback by UdpIoCreatePort() when creating UdpIo for this Dhcp4 instance.
1179
1180 @param[in] UdpIo The UdpIo being created.
1181 @param[in] Context Dhcp4 instance.
1182
1183 @retval EFI_SUCCESS UdpIo is configured successfully.
1184 @retval EFI_INVALID_PARAMETER Class E IP address is not supported or other parameters
1185 are not valid.
1186 @retval other Other error occurs.
1187 **/
1188 EFI_STATUS
1189 EFIAPI
1190 Dhcp4InstanceConfigUdpIo (
1191 IN UDP_IO *UdpIo,
1192 IN VOID *Context
1193 )
1194 {
1195 DHCP_PROTOCOL *Instance;
1196 DHCP_SERVICE *DhcpSb;
1197 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
1198 EFI_UDP4_CONFIG_DATA UdpConfigData;
1199 IP4_ADDR ClientAddr;
1200 IP4_ADDR Ip;
1201 INTN Class;
1202 IP4_ADDR SubnetMask;
1203
1204 Instance = (DHCP_PROTOCOL *) Context;
1205 DhcpSb = Instance->Service;
1206 Token = Instance->Token;
1207
1208 ZeroMem (&UdpConfigData, sizeof (EFI_UDP4_CONFIG_DATA));
1209
1210 UdpConfigData.AcceptBroadcast = TRUE;
1211 UdpConfigData.AllowDuplicatePort = TRUE;
1212 UdpConfigData.TimeToLive = 64;
1213 UdpConfigData.DoNotFragment = TRUE;
1214
1215 ClientAddr = EFI_NTOHL (Token->Packet->Dhcp4.Header.ClientAddr);
1216 Ip = HTONL (ClientAddr);
1217 CopyMem (&UdpConfigData.StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
1218
1219 if (DhcpSb->Netmask == 0) {
1220 //
1221 // The Dhcp4.TransmitReceive() API should be able to used at any time according to
1222 // UEFI spec, while in classless addressing network, the netmask must be explicitly
1223 // provided together with the station address.
1224 // If the DHCP instance haven't be configured with a valid netmask, we could only
1225 // compute it according to the classful addressing rule.
1226 //
1227 Class = NetGetIpClass (ClientAddr);
1228 //
1229 // Class E IP address is not supported here!
1230 //
1231 ASSERT (Class < IP4_ADDR_CLASSE);
1232 if (Class >= IP4_ADDR_CLASSE) {
1233 return EFI_INVALID_PARAMETER;
1234 }
1235
1236 SubnetMask = gIp4AllMasks[Class << 3];
1237 } else {
1238 SubnetMask = DhcpSb->Netmask;
1239 }
1240
1241 Ip = HTONL (SubnetMask);
1242 CopyMem (&UdpConfigData.SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
1243
1244 if ((Token->ListenPointCount == 0) || (Token->ListenPoints[0].ListenPort == 0)) {
1245 UdpConfigData.StationPort = DHCP_CLIENT_PORT;
1246 } else {
1247 UdpConfigData.StationPort = Token->ListenPoints[0].ListenPort;
1248 }
1249
1250 return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);
1251 }
1252
1253 /**
1254 Create UdpIo for this Dhcp4 instance.
1255
1256 @param Instance The Dhcp4 instance.
1257
1258 @retval EFI_SUCCESS UdpIo is created successfully.
1259 @retval EFI_OUT_OF_RESOURCES Fails to create UdpIo because of limited
1260 resources or configuration failure.
1261 **/
1262 EFI_STATUS
1263 Dhcp4InstanceCreateUdpIo (
1264 IN OUT DHCP_PROTOCOL *Instance
1265 )
1266 {
1267 DHCP_SERVICE *DhcpSb;
1268 EFI_STATUS Status;
1269 VOID *Udp4;
1270
1271 ASSERT (Instance->Token != NULL);
1272
1273 DhcpSb = Instance->Service;
1274 Instance->UdpIo = UdpIoCreateIo (
1275 DhcpSb->Controller,
1276 DhcpSb->Image,
1277 Dhcp4InstanceConfigUdpIo,
1278 UDP_IO_UDP4_VERSION,
1279 Instance
1280 );
1281 if (Instance->UdpIo == NULL) {
1282 return EFI_OUT_OF_RESOURCES;
1283 } else {
1284 Status = gBS->OpenProtocol (
1285 Instance->UdpIo->UdpHandle,
1286 &gEfiUdp4ProtocolGuid,
1287 (VOID **) &Udp4,
1288 Instance->Service->Image,
1289 Instance->Handle,
1290 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1291 );
1292 if (EFI_ERROR (Status)) {
1293 UdpIoFreeIo (Instance->UdpIo);
1294 Instance->UdpIo = NULL;
1295 }
1296 return Status;
1297 }
1298 }
1299
1300 /**
1301 Callback of Dhcp packet. Does nothing.
1302
1303 @param Arg The context.
1304
1305 **/
1306 VOID
1307 EFIAPI
1308 DhcpDummyExtFree (
1309 IN VOID *Arg
1310 )
1311 {
1312 }
1313
1314 /**
1315 Callback of UdpIoRecvDatagram() that handles a Dhcp4 packet.
1316
1317 Only BOOTP responses will be handled that correspond to the Xid of the request
1318 sent out. The packet will be queued to the response queue.
1319
1320 @param UdpPacket The Dhcp4 packet.
1321 @param EndPoint Udp4 address pair.
1322 @param IoStatus Status of the input.
1323 @param Context Extra info for the input.
1324
1325 **/
1326 VOID
1327 EFIAPI
1328 PxeDhcpInput (
1329 NET_BUF *UdpPacket,
1330 UDP_END_POINT *EndPoint,
1331 EFI_STATUS IoStatus,
1332 VOID *Context
1333 )
1334 {
1335 DHCP_PROTOCOL *Instance;
1336 EFI_DHCP4_HEADER *Head;
1337 NET_BUF *Wrap;
1338 EFI_DHCP4_PACKET *Packet;
1339 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
1340 UINT32 Len;
1341 EFI_STATUS Status;
1342
1343 Wrap = NULL;
1344 Instance = (DHCP_PROTOCOL *) Context;
1345 Token = Instance->Token;
1346
1347 //
1348 // Don't restart receive if error occurs or DHCP is destroyed.
1349 //
1350 if (EFI_ERROR (IoStatus)) {
1351 return ;
1352 }
1353
1354 ASSERT (UdpPacket != NULL);
1355
1356 //
1357 // Validate the packet received
1358 //
1359 if (UdpPacket->TotalSize < sizeof (EFI_DHCP4_HEADER)) {
1360 goto RESTART;
1361 }
1362
1363 //
1364 // Copy the DHCP message to a continuous memory block, make the buffer size
1365 // of the EFI_DHCP4_PACKET a multiple of 4-byte.
1366 //
1367 Len = NET_ROUNDUP (sizeof (EFI_DHCP4_PACKET) + UdpPacket->TotalSize - sizeof (EFI_DHCP4_HEADER), 4);
1368 Wrap = NetbufAlloc (Len);
1369 if (Wrap == NULL) {
1370 goto RESTART;
1371 }
1372
1373 Packet = (EFI_DHCP4_PACKET *) NetbufAllocSpace (Wrap, Len, NET_BUF_TAIL);
1374 ASSERT (Packet != NULL);
1375
1376 Packet->Size = Len;
1377 Head = &Packet->Dhcp4.Header;
1378 Packet->Length = NetbufCopy (UdpPacket, 0, UdpPacket->TotalSize, (UINT8 *) Head);
1379
1380 if (Packet->Length != UdpPacket->TotalSize) {
1381 goto RESTART;
1382 }
1383
1384 //
1385 // Is this packet the answer to our packet?
1386 //
1387 if ((Head->OpCode != BOOTP_REPLY) ||
1388 (Head->Xid != Token->Packet->Dhcp4.Header.Xid) ||
1389 (CompareMem (&Token->Packet->Dhcp4.Header.ClientHwAddr[0], Head->ClientHwAddr, Head->HwAddrLen) != 0)) {
1390 goto RESTART;
1391 }
1392
1393 //
1394 // Validate the options and retrieve the interested options
1395 //
1396 if ((Packet->Length > sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)) &&
1397 (Packet->Dhcp4.Magik == DHCP_OPTION_MAGIC) &&
1398 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {
1399
1400 goto RESTART;
1401 }
1402
1403 //
1404 // Keep this packet in the ResponseQueue.
1405 //
1406 NET_GET_REF (Wrap);
1407 NetbufQueAppend (&Instance->ResponseQueue, Wrap);
1408
1409 RESTART:
1410
1411 NetbufFree (UdpPacket);
1412
1413 if (Wrap != NULL) {
1414 NetbufFree (Wrap);
1415 }
1416
1417 Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);
1418 if (EFI_ERROR (Status)) {
1419 PxeDhcpDone (Instance);
1420 }
1421 }
1422
1423 /**
1424 Complete a Dhcp4 transaction and signal the upper layer.
1425
1426 @param Instance Dhcp4 instance.
1427
1428 **/
1429 VOID
1430 PxeDhcpDone (
1431 IN DHCP_PROTOCOL *Instance
1432 )
1433 {
1434 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;
1435
1436 Token = Instance->Token;
1437
1438 Token->ResponseCount = Instance->ResponseQueue.BufNum;
1439 if (Token->ResponseCount != 0) {
1440 Token->ResponseList = (EFI_DHCP4_PACKET *) AllocatePool (Instance->ResponseQueue.BufSize);
1441 if (Token->ResponseList == NULL) {
1442 Token->Status = EFI_OUT_OF_RESOURCES;
1443 goto SIGNAL_USER;
1444 }
1445
1446 //
1447 // Copy the received DHCP responses.
1448 //
1449 NetbufQueCopy (&Instance->ResponseQueue, 0, Instance->ResponseQueue.BufSize, (UINT8 *) Token->ResponseList);
1450 Token->Status = EFI_SUCCESS;
1451 } else {
1452 Token->ResponseList = NULL;
1453 Token->Status = EFI_TIMEOUT;
1454 }
1455
1456 SIGNAL_USER:
1457 //
1458 // Clean up the resources dedicated for this transmit receive transaction.
1459 //
1460 NetbufQueFlush (&Instance->ResponseQueue);
1461 UdpIoCleanIo (Instance->UdpIo);
1462 gBS->CloseProtocol (
1463 Instance->UdpIo->UdpHandle,
1464 &gEfiUdp4ProtocolGuid,
1465 Instance->Service->Image,
1466 Instance->Handle
1467 );
1468 UdpIoFreeIo (Instance->UdpIo);
1469 Instance->UdpIo = NULL;
1470 Instance->Token = NULL;
1471
1472 if (Token->CompletionEvent != NULL) {
1473 gBS->SignalEvent (Token->CompletionEvent);
1474 }
1475 }
1476
1477
1478 /**
1479 Transmits a DHCP formatted packet and optionally waits for responses.
1480
1481 The TransmitReceive() function is used to transmit a DHCP packet and optionally
1482 wait for the response from servers. This function does not change the state of
1483 the EFI DHCPv4 Protocol driver and thus can be used at any time.
1484
1485 @param[in] This Pointer to the EFI_DHCP4_PROTOCOL instance.
1486 @param[in] Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure.
1487
1488 @retval EFI_SUCCESS The packet was successfully queued for transmission.
1489 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
1490 @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call
1491 this function after collection process completes.
1492 @retval EFI_NO_MAPPING The default station address is not available yet.
1493 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1494 @retval Others Some other unexpected error occurred.
1495
1496 **/
1497 EFI_STATUS
1498 EFIAPI
1499 EfiDhcp4TransmitReceive (
1500 IN EFI_DHCP4_PROTOCOL *This,
1501 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token
1502 )
1503 {
1504 DHCP_PROTOCOL *Instance;
1505 EFI_TPL OldTpl;
1506 EFI_STATUS Status;
1507 NET_FRAGMENT Frag;
1508 NET_BUF *Wrap;
1509 UDP_END_POINT EndPoint;
1510 IP4_ADDR Ip;
1511 DHCP_SERVICE *DhcpSb;
1512 EFI_IP_ADDRESS Gateway;
1513 IP4_ADDR ClientAddr;
1514
1515 if ((This == NULL) || (Token == NULL) || (Token->Packet == NULL)) {
1516 return EFI_INVALID_PARAMETER;
1517 }
1518
1519 Instance = DHCP_INSTANCE_FROM_THIS (This);
1520 DhcpSb = Instance->Service;
1521
1522 if (Instance->Token != NULL) {
1523 //
1524 // The previous call to TransmitReceive is not finished.
1525 //
1526 return EFI_NOT_READY;
1527 }
1528
1529 if ((Token->Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
1530 (NTOHL (Token->Packet->Dhcp4.Header.Xid) == Instance->Service->Xid) ||
1531 (Token->TimeoutValue == 0) ||
1532 ((Token->ListenPointCount != 0) && (Token->ListenPoints == NULL)) ||
1533 EFI_ERROR (DhcpValidateOptions (Token->Packet, NULL)) ||
1534 EFI_IP4_EQUAL (&Token->RemoteAddress, &mZeroIp4Addr)
1535 ) {
1536 //
1537 // The DHCP packet isn't well-formed, the Transaction ID is already used,
1538 // the timeout value is zero, the ListenPoint is invalid, or the
1539 // RemoteAddress is zero.
1540 //
1541 return EFI_INVALID_PARAMETER;
1542 }
1543
1544 ClientAddr = EFI_NTOHL (Token->Packet->Dhcp4.Header.ClientAddr);
1545
1546 if (ClientAddr == 0) {
1547 return EFI_NO_MAPPING;
1548 }
1549
1550 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1551
1552 //
1553 // Save the token and the timeout value.
1554 //
1555 Instance->Token = Token;
1556 Instance->Timeout = Token->TimeoutValue;
1557
1558 //
1559 // Create a UDP IO for this transmit receive transaction.
1560 //
1561 Status = Dhcp4InstanceCreateUdpIo (Instance);
1562 if (EFI_ERROR (Status)) {
1563 goto ON_ERROR;
1564 }
1565
1566 //
1567 // Save the Client Address is sent out
1568 //
1569 CopyMem (
1570 &DhcpSb->ClientAddressSendOut[0],
1571 &Token->Packet->Dhcp4.Header.ClientHwAddr[0],
1572 Token->Packet->Dhcp4.Header.HwAddrLen
1573 );
1574
1575 //
1576 // Wrap the DHCP packet into a net buffer.
1577 //
1578 Frag.Bulk = (UINT8 *) &Token->Packet->Dhcp4;
1579 Frag.Len = Token->Packet->Length;
1580 Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL);
1581 if (Wrap == NULL) {
1582 Status = EFI_OUT_OF_RESOURCES;
1583 goto ON_ERROR;
1584 }
1585
1586 //
1587 // Set the local address and local port to ZERO.
1588 //
1589 ZeroMem (&EndPoint, sizeof (UDP_END_POINT));
1590
1591 //
1592 // Set the destination address and destination port.
1593 //
1594 CopyMem (&Ip, &Token->RemoteAddress, sizeof (EFI_IPv4_ADDRESS));
1595 EndPoint.RemoteAddr.Addr[0] = NTOHL (Ip);
1596
1597 if (Token->RemotePort == 0) {
1598 EndPoint.RemotePort = DHCP_SERVER_PORT;
1599 } else {
1600 EndPoint.RemotePort = Token->RemotePort;
1601 }
1602
1603 //
1604 // Get the gateway.
1605 //
1606 ZeroMem (&Gateway, sizeof (Gateway));
1607 if (!IP4_NET_EQUAL (ClientAddr, EndPoint.RemoteAddr.Addr[0], DhcpSb->Netmask)) {
1608 CopyMem (&Gateway.v4, &Token->GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
1609 Gateway.Addr[0] = NTOHL (Gateway.Addr[0]);
1610 }
1611
1612 //
1613 // Transmit the DHCP packet.
1614 //
1615 Status = UdpIoSendDatagram (Instance->UdpIo, Wrap, &EndPoint, &Gateway, DhcpOnPacketSent, NULL);
1616 if (EFI_ERROR (Status)) {
1617 NetbufFree (Wrap);
1618 goto ON_ERROR;
1619 }
1620
1621 //
1622 // Start to receive the DHCP response.
1623 //
1624 Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);
1625 if (EFI_ERROR (Status)) {
1626 goto ON_ERROR;
1627 }
1628
1629 ON_ERROR:
1630
1631 if (EFI_ERROR (Status) && (Instance->UdpIo != NULL)) {
1632 UdpIoCleanIo (Instance->UdpIo);
1633 gBS->CloseProtocol (
1634 Instance->UdpIo->UdpHandle,
1635 &gEfiUdp4ProtocolGuid,
1636 Instance->Service->Image,
1637 Instance->Handle
1638 );
1639 UdpIoFreeIo (Instance->UdpIo);
1640 Instance->UdpIo = NULL;
1641 Instance->Token = NULL;
1642 }
1643
1644 gBS->RestoreTPL (OldTpl);
1645
1646 if (!EFI_ERROR (Status) && (Token->CompletionEvent == NULL)) {
1647 //
1648 // Keep polling until timeout if no error happens and the CompletionEvent
1649 // is NULL.
1650 //
1651 while (TRUE) {
1652 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1653 //
1654 // Raise TPL to protect the UDPIO in instance, in case that DhcpOnTimerTick
1655 // free it when timeout.
1656 //
1657 if (Instance->Timeout > 0) {
1658 Instance->UdpIo->Protocol.Udp4->Poll (Instance->UdpIo->Protocol.Udp4);
1659 gBS->RestoreTPL (OldTpl);
1660 } else {
1661 gBS->RestoreTPL (OldTpl);
1662 break;
1663 }
1664 }
1665 }
1666
1667 return Status;
1668 }
1669
1670
1671 /**
1672 Callback function for DhcpIterateOptions. This callback sets the
1673 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point
1674 the individual DHCP option in the packet.
1675
1676 @param[in] Tag The DHCP option type
1677 @param[in] Len Length of the DHCP option data
1678 @param[in] Data The DHCP option data
1679 @param[in] Context The context, to pass several parameters in.
1680
1681 @retval EFI_SUCCESS It always returns EFI_SUCCESS
1682
1683 **/
1684 EFI_STATUS
1685 Dhcp4ParseCheckOption (
1686 IN UINT8 Tag,
1687 IN UINT8 Len,
1688 IN UINT8 *Data,
1689 IN VOID *Context
1690 )
1691 {
1692 DHCP_PARSE_CONTEXT *Parse;
1693
1694 Parse = (DHCP_PARSE_CONTEXT *) Context;
1695 Parse->Index++;
1696
1697 if (Parse->Index <= Parse->OptionCount) {
1698 //
1699 // Use BASE_CR to get the memory position of EFI_DHCP4_PACKET_OPTION for
1700 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only
1701 // pass in the point to option data.
1702 //
1703 Parse->Option[Parse->Index - 1] = BASE_CR (Data, EFI_DHCP4_PACKET_OPTION, Data);
1704 }
1705
1706 return EFI_SUCCESS;
1707 }
1708
1709
1710 /**
1711 Parses the packed DHCP option data.
1712
1713 The Parse() function is used to retrieve the option list from a DHCP packet.
1714 If *OptionCount isn't zero, and there is enough space for all the DHCP options
1715 in the Packet, each element of PacketOptionList is set to point to somewhere in
1716 the Packet->Dhcp4.Option where a new DHCP option begins. If RFC3396 is supported,
1717 the caller should reassemble the parsed DHCP options to get the finial result.
1718 If *OptionCount is zero or there isn't enough space for all of them, the number
1719 of DHCP options in the Packet is returned in OptionCount.
1720
1721 @param This Pointer to the EFI_DHCP4_PROTOCOL instance.
1722 @param Packet Pointer to packet to be parsed.
1723 @param OptionCount On input, the number of entries in the PacketOptionList.
1724 On output, the number of entries that were written into the
1725 PacketOptionList.
1726 @param PacketOptionList List of packet option entries to be filled in. End option or pad
1727 options are not included.
1728
1729 @retval EFI_SUCCESS The packet was successfully parsed.
1730 @retval EFI_INVALID_PARAMETER Some parameter is NULL.
1731 @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE:
1732 1) *OptionCount is smaller than the number of options that
1733 were found in the Packet.
1734 2) PacketOptionList is NULL.
1735
1736 **/
1737 EFI_STATUS
1738 EFIAPI
1739 EfiDhcp4Parse (
1740 IN EFI_DHCP4_PROTOCOL *This,
1741 IN EFI_DHCP4_PACKET *Packet,
1742 IN OUT UINT32 *OptionCount,
1743 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL
1744 )
1745 {
1746 DHCP_PARSE_CONTEXT Context;
1747 EFI_STATUS Status;
1748
1749 //
1750 // First validate the parameters
1751 //
1752 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {
1753 return EFI_INVALID_PARAMETER;
1754 }
1755
1756 if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||
1757 (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
1758 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {
1759
1760 return EFI_INVALID_PARAMETER;
1761 }
1762
1763 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {
1764 return EFI_BUFFER_TOO_SMALL;
1765 }
1766
1767 ZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
1768
1769 Context.Option = PacketOptionList;
1770 Context.OptionCount = *OptionCount;
1771 Context.Index = 0;
1772
1773 Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);
1774
1775 if (EFI_ERROR (Status)) {
1776 return Status;
1777 }
1778
1779 *OptionCount = Context.Index;
1780
1781 if (Context.Index > Context.OptionCount) {
1782 return EFI_BUFFER_TOO_SMALL;
1783 }
1784
1785 return EFI_SUCCESS;
1786 }
1787
1788 /**
1789 Set the elapsed time based on the given instance and the pointer to the
1790 elapsed time option.
1791
1792 @param[in] Elapsed The pointer to the position to append.
1793 @param[in] Instance The pointer to the Dhcp4 instance.
1794 **/
1795 VOID
1796 SetElapsedTime (
1797 IN UINT16 *Elapsed,
1798 IN DHCP_PROTOCOL *Instance
1799 )
1800 {
1801 WriteUnaligned16 (Elapsed, HTONS(Instance->ElaspedTime));
1802 }