1. clean up codes.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Impl.c
1 /** @file
2
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
8
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.
11
12 Module Name:
13
14 Dhcp4Impl.c
15
16 Abstract:
17
18 This file implement the EFI_DHCP4_PROTOCOL interface.
19
20
21 **/
22
23
24 #include "Dhcp4Impl.h"
25
26
27 /**
28 Get the current operation parameter and lease for the network interface.
29
30 @param This The DHCP protocol instance
31 @param Dhcp4ModeData The variable to save the DHCP mode data.
32
33 @retval EFI_INVALID_PARAMETER The parameter is invalid
34 @retval EFI_SUCCESS The Dhcp4ModeData is updated with the current
35 operation parameter.
36
37 **/
38 STATIC
39 EFI_STATUS
40 EFIAPI
41 EfiDhcp4GetModeData (
42 IN EFI_DHCP4_PROTOCOL *This,
43 OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData
44 )
45 {
46 DHCP_PROTOCOL *Instance;
47 DHCP_SERVICE *DhcpSb;
48 DHCP_PARAMETER *Para;
49 EFI_TPL OldTpl;
50 IP4_ADDR Ip;
51
52 //
53 // First validate the parameters.
54 //
55 if ((This == NULL) || (Dhcp4ModeData == NULL)) {
56 return EFI_INVALID_PARAMETER;
57 }
58
59 Instance = DHCP_INSTANCE_FROM_THIS (This);
60
61 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
62 return EFI_INVALID_PARAMETER;
63 }
64
65 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
66 DhcpSb = Instance->Service;
67
68 //
69 // Caller can use GetModeData to retrieve current DHCP states
70 // no matter whether it is the active child or not.
71 //
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));
75
76 Ip = HTONL (DhcpSb->ClientAddr);
77 NetCopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
78
79 Ip = HTONL (DhcpSb->Netmask);
80 NetCopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));
81
82 Ip = HTONL (DhcpSb->ServerAddr);
83 NetCopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
84
85 Para = DhcpSb->Para;
86
87 if (Para != NULL) {
88 Ip = HTONL (Para->Router);
89 NetCopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));
90 Dhcp4ModeData->LeaseTime = Para->Lease;
91 } else {
92 NetZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));
93 Dhcp4ModeData->LeaseTime = 0xffffffff;
94 }
95
96 Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;
97
98 NET_RESTORE_TPL (OldTpl);
99 return EFI_SUCCESS;
100 }
101
102
103 /**
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.
107
108 @param Config The DHCP configure data
109
110 @return None
111
112 **/
113 VOID
114 DhcpCleanConfigure (
115 IN EFI_DHCP4_CONFIG_DATA *Config
116 )
117 {
118 UINT32 Index;
119
120 if (Config->DiscoverTimeout != NULL) {
121 NetFreePool (Config->DiscoverTimeout);
122 }
123
124 if (Config->RequestTimeout != NULL) {
125 NetFreePool (Config->RequestTimeout);
126 }
127
128 if (Config->OptionList != NULL) {
129 for (Index = 0; Index < Config->OptionCount; Index++) {
130 if (Config->OptionList[Index] != NULL) {
131 NetFreePool (Config->OptionList[Index]);
132 }
133 }
134
135 NetFreePool (Config->OptionList);
136 }
137
138 NetZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));
139 }
140
141
142 /**
143 Allocate memory for configure parameter such as timeout value for Dst,
144 then copy the configure parameter from Src to Dst.
145
146 @param Dst The destination DHCP configure data.
147 @param Src The source DHCP configure data.
148
149 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
150 @retval EFI_SUCCESS The configure is copied.
151
152 **/
153 EFI_STATUS
154 DhcpCopyConfigure (
155 IN EFI_DHCP4_CONFIG_DATA *Dst,
156 IN EFI_DHCP4_CONFIG_DATA *Src
157 )
158 {
159 EFI_DHCP4_PACKET_OPTION **DstOptions;
160 EFI_DHCP4_PACKET_OPTION **SrcOptions;
161 INTN Len;
162 UINT32 Index;
163
164 CopyMem (Dst, Src, sizeof (*Dst));
165 Dst->DiscoverTimeout = NULL;
166 Dst->RequestTimeout = NULL;
167 Dst->OptionList = NULL;
168
169 //
170 // Allocate a memory then copy DiscoverTimeout to it
171 //
172 if (Src->DiscoverTimeout != NULL) {
173 Len = Src->DiscoverTryCount * sizeof (UINT32);
174 Dst->DiscoverTimeout = NetAllocatePool (Len);
175
176 if (Dst->DiscoverTimeout == NULL) {
177 return EFI_OUT_OF_RESOURCES;
178 }
179
180 for (Index = 0; Index < Src->DiscoverTryCount; Index++) {
181 Dst->DiscoverTimeout[Index] = NET_MAX (Src->DiscoverTimeout[Index], 1);
182 }
183 }
184
185 //
186 // Allocate a memory then copy RequestTimeout to it
187 //
188 if (Src->RequestTimeout != NULL) {
189 Len = Src->RequestTryCount * sizeof (UINT32);
190 Dst->RequestTimeout = NetAllocatePool (Len);
191
192 if (Dst->RequestTimeout == NULL) {
193 goto ON_ERROR;
194 }
195
196 for (Index = 0; Index < Src->RequestTryCount; Index++) {
197 Dst->RequestTimeout[Index] = NET_MAX (Src->RequestTimeout[Index], 1);
198 }
199 }
200
201 //
202 // Allocate an array of dhcp option point, then allocate memory
203 // for each option and copy the source option to it
204 //
205 if (Src->OptionList != NULL) {
206 Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);
207 Dst->OptionList = NetAllocateZeroPool (Len);
208
209 if (Dst->OptionList == NULL) {
210 goto ON_ERROR;
211 }
212
213 DstOptions = Dst->OptionList;
214 SrcOptions = Src->OptionList;
215
216 for (Index = 0; Index < Src->OptionCount; Index++) {
217 Len = sizeof (EFI_DHCP4_PACKET_OPTION) + NET_MAX (SrcOptions[Index]->Length - 1, 0);
218
219 DstOptions[Index] = NetAllocatePool (Len);
220
221 if (DstOptions[Index] == NULL) {
222 goto ON_ERROR;
223 }
224
225 NetCopyMem (DstOptions[Index], SrcOptions[Index], Len);
226 }
227 }
228
229 return EFI_SUCCESS;
230
231 ON_ERROR:
232 DhcpCleanConfigure (Dst);
233 return EFI_OUT_OF_RESOURCES;
234 }
235
236
237 /**
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.
241
242 @param DhcpSb The DHCP service instance.
243
244 @return None
245
246 **/
247 VOID
248 DhcpYieldControl (
249 IN DHCP_SERVICE *DhcpSb
250 )
251 {
252 EFI_DHCP4_CONFIG_DATA *Config;
253
254 Config = &DhcpSb->ActiveConfig;
255
256 DhcpSb->ServiceState = DHCP_UNCONFIGED;
257 DhcpSb->ActiveChild = NULL;
258
259 if (Config->DiscoverTimeout != NULL) {
260 NetFreePool (Config->DiscoverTimeout);
261
262 Config->DiscoverTryCount = 0;
263 Config->DiscoverTimeout = NULL;
264 }
265
266 if (Config->RequestTimeout != NULL) {
267 NetFreePool (Config->RequestTimeout);
268
269 Config->RequestTryCount = 0;
270 Config->RequestTimeout = NULL;
271 }
272
273 Config->Dhcp4Callback = NULL;
274 Config->CallbackContext = NULL;
275 }
276
277
278 /**
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.
282
283 @param This The DHCP protocol instance
284 @param Dhcp4CfgData The DHCP configure data.
285
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.
291
292 **/
293 STATIC
294 EFI_STATUS
295 EFIAPI
296 EfiDhcp4Configure (
297 IN EFI_DHCP4_PROTOCOL *This,
298 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL
299 )
300 {
301 EFI_DHCP4_CONFIG_DATA *Config;
302 DHCP_PROTOCOL *Instance;
303 DHCP_SERVICE *DhcpSb;
304 EFI_STATUS Status;
305 EFI_TPL OldTpl;
306 UINT32 Index;
307 IP4_ADDR Ip;
308
309 //
310 // First validate the parameters
311 //
312 if (This == NULL) {
313 return EFI_INVALID_PARAMETER;
314 }
315
316 if (Dhcp4CfgData != NULL) {
317 if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {
318 return EFI_INVALID_PARAMETER;
319 }
320
321 if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {
322 return EFI_INVALID_PARAMETER;
323 }
324
325 if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {
326 return EFI_INVALID_PARAMETER;
327 }
328
329 NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));
330
331 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {
332
333 return EFI_INVALID_PARAMETER;
334 }
335 }
336
337 Instance = DHCP_INSTANCE_FROM_THIS (This);
338
339 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
340 return EFI_INVALID_PARAMETER;
341 }
342
343 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
344
345 DhcpSb = Instance->Service;
346 Config = &DhcpSb->ActiveConfig;
347
348 Status = EFI_ACCESS_DENIED;
349
350 if ((DhcpSb->DhcpState != Dhcp4Stopped) &&
351 (DhcpSb->DhcpState != Dhcp4Init) &&
352 (DhcpSb->DhcpState != Dhcp4InitReboot) &&
353 (DhcpSb->DhcpState != Dhcp4Bound)) {
354
355 goto ON_EXIT;
356 }
357
358 if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {
359 goto ON_EXIT;
360 }
361
362 if (Dhcp4CfgData != NULL) {
363 Status = EFI_OUT_OF_RESOURCES;
364 DhcpCleanConfigure (Config);
365
366 if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {
367 goto ON_EXIT;
368 }
369
370 DhcpSb->UserOptionLen = 0;
371
372 for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {
373 DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;
374 }
375
376 DhcpSb->ActiveChild = Instance;
377
378 if (DhcpSb->DhcpState == Dhcp4Stopped) {
379 DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);
380
381 if (DhcpSb->ClientAddr != 0) {
382 DhcpSb->DhcpState = Dhcp4InitReboot;
383 } else {
384 DhcpSb->DhcpState = Dhcp4Init;
385 }
386 }
387
388 DhcpSb->ServiceState = DHCP_CONFIGED;
389 Status = EFI_SUCCESS;
390
391 } else if (DhcpSb->ActiveChild == Instance) {
392 Status = EFI_SUCCESS;
393 DhcpYieldControl (DhcpSb);
394 }
395
396 ON_EXIT:
397 NET_RESTORE_TPL (OldTpl);
398 return Status;
399 }
400
401
402 /**
403 Start the DHCP process.
404
405 @param This The DHCP protocol instance
406 @param CompletionEvent The event to signal is address is acquired.
407
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.
412
413 **/
414 STATIC
415 EFI_STATUS
416 EFIAPI
417 EfiDhcp4Start (
418 IN EFI_DHCP4_PROTOCOL *This,
419 IN EFI_EVENT CompletionEvent OPTIONAL
420 )
421 {
422 DHCP_PROTOCOL *Instance;
423 DHCP_SERVICE *DhcpSb;
424 EFI_STATUS Status;
425 EFI_TPL OldTpl;
426
427 //
428 // First validate the parameters
429 //
430 if (This == NULL) {
431 return EFI_INVALID_PARAMETER;
432 }
433
434 Instance = DHCP_INSTANCE_FROM_THIS (This);
435
436 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
437 return EFI_INVALID_PARAMETER;
438 }
439
440 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
441 DhcpSb = Instance->Service;
442
443 if (DhcpSb->DhcpState == Dhcp4Stopped) {
444 Status = EFI_NOT_STARTED;
445 goto ON_ERROR;
446 }
447
448 if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {
449 Status = EFI_ALREADY_STARTED;
450 goto ON_ERROR;
451 }
452
453 DhcpSb->IoStatus = EFI_ALREADY_STARTED;
454
455 if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {
456 goto ON_ERROR;
457 }
458
459 //
460 // Start/Restart the receiving.
461 //
462 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
463
464 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
465 goto ON_ERROR;
466 }
467
468 Instance->CompletionEvent = CompletionEvent;
469
470 //
471 // Restore the TPL now, don't call poll function at NET_TPL_LOCK.
472 //
473 NET_RESTORE_TPL (OldTpl);
474
475 if (CompletionEvent == NULL) {
476 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
477 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);
478 }
479
480 return DhcpSb->IoStatus;
481 }
482
483 return EFI_SUCCESS;
484
485 ON_ERROR:
486 NET_RESTORE_TPL (OldTpl);
487 return Status;
488 }
489
490
491 /**
492 Request an extra manual renew/rebind.
493
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
497
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.
502
503 **/
504 STATIC
505 EFI_STATUS
506 EFIAPI
507 EfiDhcp4RenewRebind (
508 IN EFI_DHCP4_PROTOCOL *This,
509 IN BOOLEAN RebindRequest,
510 IN EFI_EVENT CompletionEvent OPTIONAL
511 )
512 {
513 DHCP_PROTOCOL *Instance;
514 DHCP_SERVICE *DhcpSb;
515 EFI_STATUS Status;
516 EFI_TPL OldTpl;
517
518 //
519 // First validate the parameters
520 //
521 if (This == NULL) {
522 return EFI_INVALID_PARAMETER;
523 }
524
525 Instance = DHCP_INSTANCE_FROM_THIS (This);
526
527 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
528 return EFI_INVALID_PARAMETER;
529 }
530
531 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
532 DhcpSb = Instance->Service;
533
534 if (DhcpSb->DhcpState == Dhcp4Stopped) {
535 Status = EFI_NOT_STARTED;
536 goto ON_ERROR;
537 }
538
539 if (DhcpSb->DhcpState != Dhcp4Bound) {
540 Status = EFI_ACCESS_DENIED;
541 goto ON_ERROR;
542 }
543
544 if (DHCP_IS_BOOTP (DhcpSb->Para)) {
545 return EFI_SUCCESS;
546 }
547
548 //
549 // Transit the states then send a extra DHCP request
550 //
551 if (!RebindRequest) {
552 DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);
553 } else {
554 DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);
555 }
556
557 Status = DhcpSendMessage (
558 DhcpSb,
559 DhcpSb->Selected,
560 DhcpSb->Para,
561 DHCP_MSG_REQUEST,
562 "Extra renew/rebind by the application"
563 );
564
565 if (EFI_ERROR (Status)) {
566 DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);
567 goto ON_ERROR;
568 }
569
570 DhcpSb->ExtraRefresh = TRUE;
571 DhcpSb->IoStatus = EFI_ALREADY_STARTED;
572 Instance->RenewRebindEvent = CompletionEvent;
573
574 NET_RESTORE_TPL (OldTpl);
575
576 if (CompletionEvent == NULL) {
577 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
578 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);
579 }
580
581 return DhcpSb->IoStatus;
582 }
583
584 return EFI_SUCCESS;
585
586 ON_ERROR:
587 NET_RESTORE_TPL (OldTpl);
588 return Status;
589 }
590
591
592 /**
593 Release the current acquired lease.
594
595 @param This The DHCP protocol instance
596
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
600 state.
601 @retval EFI_SUCCESS The lease is released.
602
603 **/
604 STATIC
605 EFI_STATUS
606 EFIAPI
607 EfiDhcp4Release (
608 IN EFI_DHCP4_PROTOCOL *This
609 )
610 {
611 DHCP_PROTOCOL *Instance;
612 DHCP_SERVICE *DhcpSb;
613 EFI_STATUS Status;
614 EFI_TPL OldTpl;
615
616 //
617 // First validate the parameters
618 //
619 if (This == NULL) {
620 return EFI_INVALID_PARAMETER;
621 }
622
623 Instance = DHCP_INSTANCE_FROM_THIS (This);
624
625 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
626 return EFI_INVALID_PARAMETER;
627 }
628
629 Status = EFI_SUCCESS;
630 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
631 DhcpSb = Instance->Service;
632
633 if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {
634 Status = EFI_ACCESS_DENIED;
635 goto ON_EXIT;
636 }
637
638 if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {
639 Status = DhcpSendMessage (
640 DhcpSb,
641 DhcpSb->Selected,
642 DhcpSb->Para,
643 DHCP_MSG_RELEASE,
644 NULL
645 );
646
647 if (EFI_ERROR (Status)) {
648 Status = EFI_DEVICE_ERROR;
649 goto ON_EXIT;
650 }
651 }
652
653 DhcpCleanLease (DhcpSb);
654
655 ON_EXIT:
656 NET_RESTORE_TPL (OldTpl);
657 return Status;
658 }
659
660
661 /**
662 Stop the current DHCP process. After this, other DHCP child
663 can gain control of the service, configure and use it.
664
665 @param This The DHCP protocol instance
666
667 @retval EFI_INVALID_PARAMETER The parameter is invalid.
668 @retval EFI_SUCCESS The DHCP process is stopped.
669
670 **/
671 STATIC
672 EFI_STATUS
673 EFIAPI
674 EfiDhcp4Stop (
675 IN EFI_DHCP4_PROTOCOL *This
676 )
677 {
678 DHCP_PROTOCOL *Instance;
679 DHCP_SERVICE *DhcpSb;
680 EFI_TPL OldTpl;
681
682 //
683 // First validate the parameters
684 //
685 if (This == NULL) {
686 return EFI_INVALID_PARAMETER;
687 }
688
689 Instance = DHCP_INSTANCE_FROM_THIS (This);
690
691 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
692 return EFI_INVALID_PARAMETER;
693 }
694
695 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
696 DhcpSb = Instance->Service;
697
698 DhcpCleanLease (DhcpSb);
699
700 DhcpSb->DhcpState = Dhcp4Stopped;
701 DhcpSb->ServiceState = DHCP_UNCONFIGED;
702
703 NET_RESTORE_TPL (OldTpl);
704 return EFI_SUCCESS;
705 }
706
707
708 /**
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.
711
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
719 function.
720
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.
724
725 **/
726 STATIC
727 EFI_STATUS
728 EFIAPI
729 EfiDhcp4Build (
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
737 )
738 {
739 //
740 // First validate the parameters
741 //
742 if ((This == NULL) || (NewPacket == NULL)) {
743 return EFI_INVALID_PARAMETER;
744 }
745
746 if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
747 EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {
748
749 return EFI_INVALID_PARAMETER;
750 }
751
752 if (((DeleteCount == 0) && (AppendCount == 0)) ||
753 ((DeleteCount != 0) && (DeleteList == NULL)) ||
754 ((AppendCount != 0) && (AppendList == NULL))) {
755
756 return EFI_INVALID_PARAMETER;
757 }
758
759 return DhcpBuild (
760 SeedPacket,
761 DeleteCount,
762 DeleteList,
763 AppendCount,
764 AppendList,
765 NewPacket
766 );
767 }
768
769
770 /**
771 Transmit and receive a packet through this DHCP service.
772 This is unsupported.
773
774 @param This The DHCP protocol instance
775 @param Token The transmit and receive instance
776
777 @retval EFI_UNSUPPORTED It always returns unsupported.
778
779 **/
780 STATIC
781 EFI_STATUS
782 EFIAPI
783 EfiDhcp4TransmitReceive (
784 IN EFI_DHCP4_PROTOCOL *This,
785 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token
786 )
787 {
788 //
789 // This function is for PXE, leave it for now
790 //
791 return EFI_UNSUPPORTED;
792 }
793
794
795 /**
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.
799
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.
804
805 @retval EFI_SUCCESS It always returns EFI_SUCCESS
806
807 **/
808 STATIC
809 EFI_STATUS
810 Dhcp4ParseCheckOption (
811 IN UINT8 Tag,
812 IN UINT8 Len,
813 IN UINT8 *Data,
814 IN VOID *Context
815 )
816 {
817 DHCP_PARSE_CONTEXT *Parse;
818
819 Parse = (DHCP_PARSE_CONTEXT *) Context;
820 Parse->Index++;
821
822 if (Parse->Index < Parse->OptionCount) {
823 //
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.
827 //
828 Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);
829 }
830
831 return EFI_SUCCESS;
832 }
833
834
835 /**
836 Parse the DHCP options in the Packet into the PacketOptionList.
837 User should allocate this array of EFI_DHCP4_PACKET_OPTION points.
838
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
844
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.
848
849 **/
850 STATIC
851 EFI_STATUS
852 EFIAPI
853 EfiDhcp4Parse (
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
858 )
859 {
860 DHCP_PARSE_CONTEXT Context;
861 EFI_STATUS Status;
862
863 //
864 // First validate the parameters
865 //
866 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {
867 return EFI_INVALID_PARAMETER;
868 }
869
870 if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||
871 (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
872 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {
873
874 return EFI_INVALID_PARAMETER;
875 }
876
877 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {
878 return EFI_BUFFER_TOO_SMALL;
879 }
880
881 NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
882
883 Context.Option = PacketOptionList;
884 Context.OptionCount = *OptionCount;
885 Context.Index = 0;
886
887 Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);
888
889 if (EFI_ERROR (Status)) {
890 return Status;
891 }
892
893 *OptionCount = Context.Index;
894
895 if (Context.Index > Context.OptionCount) {
896 return EFI_BUFFER_TOO_SMALL;
897 }
898
899 return EFI_SUCCESS;
900 }
901
902 EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {
903 EfiDhcp4GetModeData,
904 EfiDhcp4Configure,
905 EfiDhcp4Start,
906 EfiDhcp4RenewRebind,
907 EfiDhcp4Release,
908 EfiDhcp4Stop,
909 EfiDhcp4Build,
910 EfiDhcp4TransmitReceive,
911 EfiDhcp4Parse
912 };