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