3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This file implement the EFI_DHCP4_PROTOCOL interface.
24 #include "Dhcp4Impl.h"
28 Get the current operation parameter and lease for the network interface.
30 @param This The DHCP protocol instance
31 @param Dhcp4ModeData The variable to save the DHCP mode data.
33 @retval EFI_INVALID_PARAMETER The parameter is invalid
34 @retval EFI_SUCCESS The Dhcp4ModeData is updated with the current
42 IN EFI_DHCP4_PROTOCOL
*This
,
43 OUT EFI_DHCP4_MODE_DATA
*Dhcp4ModeData
46 DHCP_PROTOCOL
*Instance
;
53 // First validate the parameters.
55 if ((This
== NULL
) || (Dhcp4ModeData
== NULL
)) {
56 return EFI_INVALID_PARAMETER
;
59 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
61 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
62 return EFI_INVALID_PARAMETER
;
65 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
66 DhcpSb
= Instance
->Service
;
69 // Caller can use GetModeData to retrieve current DHCP states
70 // no matter whether it is the active child or not.
72 Dhcp4ModeData
->State
= (EFI_DHCP4_STATE
) DhcpSb
->DhcpState
;
73 CopyMem (&Dhcp4ModeData
->ConfigData
, &DhcpSb
->ActiveConfig
, sizeof (Dhcp4ModeData
->ConfigData
));
74 CopyMem (&Dhcp4ModeData
->ClientMacAddress
, &DhcpSb
->Mac
, sizeof (Dhcp4ModeData
->ClientMacAddress
));
76 Ip
= HTONL (DhcpSb
->ClientAddr
);
77 NetCopyMem (&Dhcp4ModeData
->ClientAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
79 Ip
= HTONL (DhcpSb
->Netmask
);
80 NetCopyMem (&Dhcp4ModeData
->SubnetMask
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
82 Ip
= HTONL (DhcpSb
->ServerAddr
);
83 NetCopyMem (&Dhcp4ModeData
->ServerAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
88 Ip
= HTONL (Para
->Router
);
89 NetCopyMem (&Dhcp4ModeData
->RouterAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
90 Dhcp4ModeData
->LeaseTime
= Para
->Lease
;
92 NetZeroMem (&Dhcp4ModeData
->RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
93 Dhcp4ModeData
->LeaseTime
= 0xffffffff;
96 Dhcp4ModeData
->ReplyPacket
= DhcpSb
->Selected
;
98 NET_RESTORE_TPL (OldTpl
);
104 Free the resource related to the configure parameters.
105 DHCP driver will make a copy of the user's configure
106 such as the time out value.
108 @param Config The DHCP configure data
115 IN EFI_DHCP4_CONFIG_DATA
*Config
120 if (Config
->DiscoverTimeout
!= NULL
) {
121 NetFreePool (Config
->DiscoverTimeout
);
124 if (Config
->RequestTimeout
!= NULL
) {
125 NetFreePool (Config
->RequestTimeout
);
128 if (Config
->OptionList
!= NULL
) {
129 for (Index
= 0; Index
< Config
->OptionCount
; Index
++) {
130 if (Config
->OptionList
[Index
] != NULL
) {
131 NetFreePool (Config
->OptionList
[Index
]);
135 NetFreePool (Config
->OptionList
);
138 NetZeroMem (Config
, sizeof (EFI_DHCP4_CONFIG_DATA
));
143 Allocate memory for configure parameter such as timeout value for Dst,
144 then copy the configure parameter from Src to Dst.
146 @param Dst The destination DHCP configure data.
147 @param Src The source DHCP configure data.
149 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
150 @retval EFI_SUCCESS The configure is copied.
155 IN EFI_DHCP4_CONFIG_DATA
*Dst
,
156 IN EFI_DHCP4_CONFIG_DATA
*Src
159 EFI_DHCP4_PACKET_OPTION
**DstOptions
;
160 EFI_DHCP4_PACKET_OPTION
**SrcOptions
;
164 CopyMem (Dst
, Src
, sizeof (*Dst
));
165 Dst
->DiscoverTimeout
= NULL
;
166 Dst
->RequestTimeout
= NULL
;
167 Dst
->OptionList
= NULL
;
170 // Allocate a memory then copy DiscoverTimeout to it
172 if (Src
->DiscoverTimeout
!= NULL
) {
173 Len
= Src
->DiscoverTryCount
* sizeof (UINT32
);
174 Dst
->DiscoverTimeout
= NetAllocatePool (Len
);
176 if (Dst
->DiscoverTimeout
== NULL
) {
177 return EFI_OUT_OF_RESOURCES
;
180 for (Index
= 0; Index
< Src
->DiscoverTryCount
; Index
++) {
181 Dst
->DiscoverTimeout
[Index
] = NET_MAX (Src
->DiscoverTimeout
[Index
], 1);
186 // Allocate a memory then copy RequestTimeout to it
188 if (Src
->RequestTimeout
!= NULL
) {
189 Len
= Src
->RequestTryCount
* sizeof (UINT32
);
190 Dst
->RequestTimeout
= NetAllocatePool (Len
);
192 if (Dst
->RequestTimeout
== NULL
) {
196 for (Index
= 0; Index
< Src
->RequestTryCount
; Index
++) {
197 Dst
->RequestTimeout
[Index
] = NET_MAX (Src
->RequestTimeout
[Index
], 1);
202 // Allocate an array of dhcp option point, then allocate memory
203 // for each option and copy the source option to it
205 if (Src
->OptionList
!= NULL
) {
206 Len
= Src
->OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*);
207 Dst
->OptionList
= NetAllocateZeroPool (Len
);
209 if (Dst
->OptionList
== NULL
) {
213 DstOptions
= Dst
->OptionList
;
214 SrcOptions
= Src
->OptionList
;
216 for (Index
= 0; Index
< Src
->OptionCount
; Index
++) {
217 Len
= sizeof (EFI_DHCP4_PACKET_OPTION
) + NET_MAX (SrcOptions
[Index
]->Length
- 1, 0);
219 DstOptions
[Index
] = NetAllocatePool (Len
);
221 if (DstOptions
[Index
] == NULL
) {
225 NetCopyMem (DstOptions
[Index
], SrcOptions
[Index
], Len
);
232 DhcpCleanConfigure (Dst
);
233 return EFI_OUT_OF_RESOURCES
;
238 Give up the control of the DHCP service to let other child
239 resume. Don't change the service's DHCP state and the Client
240 address and option list configure as required by RFC2131.
242 @param DhcpSb The DHCP service instance.
249 IN DHCP_SERVICE
*DhcpSb
252 EFI_DHCP4_CONFIG_DATA
*Config
;
254 Config
= &DhcpSb
->ActiveConfig
;
256 DhcpSb
->ServiceState
= DHCP_UNCONFIGED
;
257 DhcpSb
->ActiveChild
= NULL
;
259 if (Config
->DiscoverTimeout
!= NULL
) {
260 NetFreePool (Config
->DiscoverTimeout
);
262 Config
->DiscoverTryCount
= 0;
263 Config
->DiscoverTimeout
= NULL
;
266 if (Config
->RequestTimeout
!= NULL
) {
267 NetFreePool (Config
->RequestTimeout
);
269 Config
->RequestTryCount
= 0;
270 Config
->RequestTimeout
= NULL
;
273 Config
->Dhcp4Callback
= NULL
;
274 Config
->CallbackContext
= NULL
;
279 Configure the DHCP protocol instance and its underlying DHCP service
280 for operation. If Dhcp4CfgData is NULL and the child is currently
281 controlling the DHCP service, release the control.
283 @param This The DHCP protocol instance
284 @param Dhcp4CfgData The DHCP configure data.
286 @retval EFI_INVALID_PARAMETER The parameters are invalid.
287 @retval EFI_ACCESS_DENIED The service isn't in one of configurable states,
288 or there is already an active child.
289 @retval EFI_OUT_OF_RESOURCE Failed to allocate some resources.
290 @retval EFI_SUCCESS The child is configured.
297 IN EFI_DHCP4_PROTOCOL
*This
,
298 IN EFI_DHCP4_CONFIG_DATA
*Dhcp4CfgData OPTIONAL
301 EFI_DHCP4_CONFIG_DATA
*Config
;
302 DHCP_PROTOCOL
*Instance
;
303 DHCP_SERVICE
*DhcpSb
;
310 // First validate the parameters
313 return EFI_INVALID_PARAMETER
;
316 if (Dhcp4CfgData
!= NULL
) {
317 if (Dhcp4CfgData
->DiscoverTryCount
&& (Dhcp4CfgData
->DiscoverTimeout
== NULL
)) {
318 return EFI_INVALID_PARAMETER
;
321 if (Dhcp4CfgData
->RequestTryCount
&& (Dhcp4CfgData
->RequestTimeout
== NULL
)) {
322 return EFI_INVALID_PARAMETER
;
325 if (Dhcp4CfgData
->OptionCount
&& (Dhcp4CfgData
->OptionList
== NULL
)) {
326 return EFI_INVALID_PARAMETER
;
329 NetCopyMem (&Ip
, &Dhcp4CfgData
->ClientAddress
, sizeof (IP4_ADDR
));
331 if ((Ip
!= 0) && !Ip4IsUnicast (NTOHL (Ip
), 0)) {
333 return EFI_INVALID_PARAMETER
;
337 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
339 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
340 return EFI_INVALID_PARAMETER
;
343 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
345 DhcpSb
= Instance
->Service
;
346 Config
= &DhcpSb
->ActiveConfig
;
348 Status
= EFI_ACCESS_DENIED
;
350 if ((DhcpSb
->DhcpState
!= Dhcp4Stopped
) &&
351 (DhcpSb
->DhcpState
!= Dhcp4Init
) &&
352 (DhcpSb
->DhcpState
!= Dhcp4InitReboot
) &&
353 (DhcpSb
->DhcpState
!= Dhcp4Bound
)) {
358 if ((DhcpSb
->ActiveChild
!= NULL
) && (DhcpSb
->ActiveChild
!= Instance
)) {
362 if (Dhcp4CfgData
!= NULL
) {
363 Status
= EFI_OUT_OF_RESOURCES
;
364 DhcpCleanConfigure (Config
);
366 if (EFI_ERROR (DhcpCopyConfigure (Config
, Dhcp4CfgData
))) {
370 DhcpSb
->UserOptionLen
= 0;
372 for (Index
= 0; Index
< Dhcp4CfgData
->OptionCount
; Index
++) {
373 DhcpSb
->UserOptionLen
+= Dhcp4CfgData
->OptionList
[Index
]->Length
+ 2;
376 DhcpSb
->ActiveChild
= Instance
;
378 if (DhcpSb
->DhcpState
== Dhcp4Stopped
) {
379 DhcpSb
->ClientAddr
= EFI_NTOHL (Dhcp4CfgData
->ClientAddress
);
381 if (DhcpSb
->ClientAddr
!= 0) {
382 DhcpSb
->DhcpState
= Dhcp4InitReboot
;
384 DhcpSb
->DhcpState
= Dhcp4Init
;
388 DhcpSb
->ServiceState
= DHCP_CONFIGED
;
389 Status
= EFI_SUCCESS
;
391 } else if (DhcpSb
->ActiveChild
== Instance
) {
392 Status
= EFI_SUCCESS
;
393 DhcpYieldControl (DhcpSb
);
397 NET_RESTORE_TPL (OldTpl
);
403 Start the DHCP process.
405 @param This The DHCP protocol instance
406 @param CompletionEvent The event to signal is address is acquired.
408 @retval EFI_INVALID_PARAMETER The parameters are invalid.
409 @retval EFI_NOT_STARTED The protocol hasn't been configured.
410 @retval EFI_ALREADY_STARTED The DHCP process has already been started.
411 @retval EFI_SUCCESS The DHCP process is started.
418 IN EFI_DHCP4_PROTOCOL
*This
,
419 IN EFI_EVENT CompletionEvent OPTIONAL
422 DHCP_PROTOCOL
*Instance
;
423 DHCP_SERVICE
*DhcpSb
;
428 // First validate the parameters
431 return EFI_INVALID_PARAMETER
;
434 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
436 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
437 return EFI_INVALID_PARAMETER
;
440 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
441 DhcpSb
= Instance
->Service
;
443 if (DhcpSb
->DhcpState
== Dhcp4Stopped
) {
444 Status
= EFI_NOT_STARTED
;
448 if ((DhcpSb
->DhcpState
!= Dhcp4Init
) && (DhcpSb
->DhcpState
!= Dhcp4InitReboot
)) {
449 Status
= EFI_ALREADY_STARTED
;
453 DhcpSb
->IoStatus
= EFI_ALREADY_STARTED
;
455 if (EFI_ERROR (Status
= DhcpInitRequest (DhcpSb
))) {
460 // Start/Restart the receiving.
462 Status
= UdpIoRecvDatagram (DhcpSb
->UdpIo
, DhcpInput
, DhcpSb
, 0);
464 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
468 Instance
->CompletionEvent
= CompletionEvent
;
471 // Restore the TPL now, don't call poll function at NET_TPL_LOCK.
473 NET_RESTORE_TPL (OldTpl
);
475 if (CompletionEvent
== NULL
) {
476 while (DhcpSb
->IoStatus
== EFI_ALREADY_STARTED
) {
477 DhcpSb
->UdpIo
->Udp
->Poll (DhcpSb
->UdpIo
->Udp
);
480 return DhcpSb
->IoStatus
;
486 NET_RESTORE_TPL (OldTpl
);
492 Request an extra manual renew/rebind.
494 @param This The DHCP protocol instance
495 @param RebindRequest TRUE if request a rebind, otherwise renew it
496 @param CompletionEvent Event to signal when complete
498 @retval EFI_INVALID_PARAMETER The parameters are invalid
499 @retval EFI_NOT_STARTED The DHCP protocol hasn't been started.
500 @retval EFI_ACCESS_DENIED The DHCP protocol isn't in Bound state.
501 @retval EFI_SUCCESS The DHCP is renewed/rebound.
507 EfiDhcp4RenewRebind (
508 IN EFI_DHCP4_PROTOCOL
*This
,
509 IN BOOLEAN RebindRequest
,
510 IN EFI_EVENT CompletionEvent OPTIONAL
513 DHCP_PROTOCOL
*Instance
;
514 DHCP_SERVICE
*DhcpSb
;
519 // First validate the parameters
522 return EFI_INVALID_PARAMETER
;
525 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
527 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
528 return EFI_INVALID_PARAMETER
;
531 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
532 DhcpSb
= Instance
->Service
;
534 if (DhcpSb
->DhcpState
== Dhcp4Stopped
) {
535 Status
= EFI_NOT_STARTED
;
539 if (DhcpSb
->DhcpState
!= Dhcp4Bound
) {
540 Status
= EFI_ACCESS_DENIED
;
544 if (DHCP_IS_BOOTP (DhcpSb
->Para
)) {
549 // Transit the states then send a extra DHCP request
551 if (!RebindRequest
) {
552 DhcpSetState (DhcpSb
, Dhcp4Renewing
, FALSE
);
554 DhcpSetState (DhcpSb
, Dhcp4Rebinding
, FALSE
);
557 Status
= DhcpSendMessage (
562 (UINT8
*) "Extra renew/rebind by the application"
565 if (EFI_ERROR (Status
)) {
566 DhcpSetState (DhcpSb
, Dhcp4Bound
, FALSE
);
570 DhcpSb
->ExtraRefresh
= TRUE
;
571 DhcpSb
->IoStatus
= EFI_ALREADY_STARTED
;
572 Instance
->RenewRebindEvent
= CompletionEvent
;
574 NET_RESTORE_TPL (OldTpl
);
576 if (CompletionEvent
== NULL
) {
577 while (DhcpSb
->IoStatus
== EFI_ALREADY_STARTED
) {
578 DhcpSb
->UdpIo
->Udp
->Poll (DhcpSb
->UdpIo
->Udp
);
581 return DhcpSb
->IoStatus
;
587 NET_RESTORE_TPL (OldTpl
);
593 Release the current acquired lease.
595 @param This The DHCP protocol instance
597 @retval EFI_INVALID_PARAMETER The parameter is invalid
598 @retval EFI_DEVICE_ERROR Failed to transmit the DHCP release packet
599 @retval EFI_ACCESS_DENIED The DHCP service isn't in one of the connected
601 @retval EFI_SUCCESS The lease is released.
608 IN EFI_DHCP4_PROTOCOL
*This
611 DHCP_PROTOCOL
*Instance
;
612 DHCP_SERVICE
*DhcpSb
;
617 // First validate the parameters
620 return EFI_INVALID_PARAMETER
;
623 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
625 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
626 return EFI_INVALID_PARAMETER
;
629 Status
= EFI_SUCCESS
;
630 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
631 DhcpSb
= Instance
->Service
;
633 if ((DhcpSb
->DhcpState
!= Dhcp4InitReboot
) && (DhcpSb
->DhcpState
!= Dhcp4Bound
)) {
634 Status
= EFI_ACCESS_DENIED
;
638 if (!DHCP_IS_BOOTP (DhcpSb
->Para
) && (DhcpSb
->DhcpState
== Dhcp4Bound
)) {
639 Status
= DhcpSendMessage (
647 if (EFI_ERROR (Status
)) {
648 Status
= EFI_DEVICE_ERROR
;
653 DhcpCleanLease (DhcpSb
);
656 NET_RESTORE_TPL (OldTpl
);
662 Stop the current DHCP process. After this, other DHCP child
663 can gain control of the service, configure and use it.
665 @param This The DHCP protocol instance
667 @retval EFI_INVALID_PARAMETER The parameter is invalid.
668 @retval EFI_SUCCESS The DHCP process is stopped.
675 IN EFI_DHCP4_PROTOCOL
*This
678 DHCP_PROTOCOL
*Instance
;
679 DHCP_SERVICE
*DhcpSb
;
683 // First validate the parameters
686 return EFI_INVALID_PARAMETER
;
689 Instance
= DHCP_INSTANCE_FROM_THIS (This
);
691 if (Instance
->Signature
!= DHCP_PROTOCOL_SIGNATURE
) {
692 return EFI_INVALID_PARAMETER
;
695 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
696 DhcpSb
= Instance
->Service
;
698 DhcpCleanLease (DhcpSb
);
700 DhcpSb
->DhcpState
= Dhcp4Stopped
;
701 DhcpSb
->ServiceState
= DHCP_UNCONFIGED
;
703 NET_RESTORE_TPL (OldTpl
);
709 Build a new DHCP packet from the seed packet. Options may be deleted or
710 appended. The caller should free the NewPacket when finished using it.
712 @param This The DHCP protocol instance.
713 @param SeedPacket The seed packet to start with
714 @param DeleteCount The number of options to delete
715 @param DeleteList The options to delete from the packet
716 @param AppendCount The number of options to append
717 @param AppendList The options to append to the packet
718 @param NewPacket The new packet, allocated and built by this
721 @retval EFI_INVALID_PARAMETER The parameters are invalid.
722 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory
723 @retval EFI_SUCCESS The packet is build.
730 IN EFI_DHCP4_PROTOCOL
*This
,
731 IN EFI_DHCP4_PACKET
*SeedPacket
,
732 IN UINT32 DeleteCount
,
733 IN UINT8
*DeleteList OPTIONAL
,
734 IN UINT32 AppendCount
,
735 IN EFI_DHCP4_PACKET_OPTION
*AppendList
[] OPTIONAL
,
736 OUT EFI_DHCP4_PACKET
**NewPacket
740 // First validate the parameters
742 if ((This
== NULL
) || (NewPacket
== NULL
)) {
743 return EFI_INVALID_PARAMETER
;
746 if ((SeedPacket
== NULL
) || (SeedPacket
->Dhcp4
.Magik
!= DHCP_OPTION_MAGIC
) ||
747 EFI_ERROR (DhcpValidateOptions (SeedPacket
, NULL
))) {
749 return EFI_INVALID_PARAMETER
;
752 if (((DeleteCount
== 0) && (AppendCount
== 0)) ||
753 ((DeleteCount
!= 0) && (DeleteList
== NULL
)) ||
754 ((AppendCount
!= 0) && (AppendList
== NULL
))) {
756 return EFI_INVALID_PARAMETER
;
771 Transmit and receive a packet through this DHCP service.
774 @param This The DHCP protocol instance
775 @param Token The transmit and receive instance
777 @retval EFI_UNSUPPORTED It always returns unsupported.
783 EfiDhcp4TransmitReceive (
784 IN EFI_DHCP4_PROTOCOL
*This
,
785 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
*Token
789 // This function is for PXE, leave it for now
791 return EFI_UNSUPPORTED
;
796 Callback function for DhcpIterateOptions. This callback sets the
797 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point
798 the individual DHCP option in the packet.
800 @param Tag The DHCP option type
801 @param Len length of the DHCP option data
802 @param Data The DHCP option data
803 @param Context The context, to pass several parameters in.
805 @retval EFI_SUCCESS It always returns EFI_SUCCESS
810 Dhcp4ParseCheckOption (
817 DHCP_PARSE_CONTEXT
*Parse
;
819 Parse
= (DHCP_PARSE_CONTEXT
*) Context
;
822 if (Parse
->Index
< Parse
->OptionCount
) {
824 // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for
825 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only
826 // pass in the point to option data.
828 Parse
->Option
[Parse
->Index
- 1] = _CR (Data
, EFI_DHCP4_PACKET_OPTION
, Data
);
836 Parse the DHCP options in the Packet into the PacketOptionList.
837 User should allocate this array of EFI_DHCP4_PACKET_OPTION points.
839 @param This The DHCP protocol instance
840 @param Packet The DHCP packet to parse
841 @param OptionCount On input, the size of the PacketOptionList; On
842 output, the actual number of options processed.
843 @param PacketOptionList The array of EFI_DHCP4_PACKET_OPTION points
845 @retval EFI_INVALID_PARAMETER The parameters are invalid.
846 @retval EFI_BUFFER_TOO_SMALL A bigger array of points is needed.
847 @retval EFI_SUCCESS The options are parsed.
854 IN EFI_DHCP4_PROTOCOL
*This
,
855 IN EFI_DHCP4_PACKET
*Packet
,
856 IN OUT UINT32
*OptionCount
,
857 OUT EFI_DHCP4_PACKET_OPTION
*PacketOptionList
[] OPTIONAL
860 DHCP_PARSE_CONTEXT Context
;
864 // First validate the parameters
866 if ((This
== NULL
) || (Packet
== NULL
) || (OptionCount
== NULL
)) {
867 return EFI_INVALID_PARAMETER
;
870 if ((Packet
->Size
< Packet
->Length
+ 2 * sizeof (UINT32
)) ||
871 (Packet
->Dhcp4
.Magik
!= DHCP_OPTION_MAGIC
) ||
872 EFI_ERROR (DhcpValidateOptions (Packet
, NULL
))) {
874 return EFI_INVALID_PARAMETER
;
877 if ((*OptionCount
!= 0) && (PacketOptionList
== NULL
)) {
878 return EFI_BUFFER_TOO_SMALL
;
881 NetZeroMem (PacketOptionList
, *OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
883 Context
.Option
= PacketOptionList
;
884 Context
.OptionCount
= *OptionCount
;
887 Status
= DhcpIterateOptions (Packet
, Dhcp4ParseCheckOption
, &Context
);
889 if (EFI_ERROR (Status
)) {
893 *OptionCount
= Context
.Index
;
895 if (Context
.Index
> Context
.OptionCount
) {
896 return EFI_BUFFER_TOO_SMALL
;
902 EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate
= {
910 EfiDhcp4TransmitReceive
,