]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
Import ArpDxe, Dhcp4Dxe, Ip4Dxe, Mtftp4Dxe, PxeBcDxe and PxeDhcp4Dxe.
[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 = DhcpSb->DhcpState;
73 CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (EFI_DHCP4_CONFIG_DATA));
74 CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (EFI_MAC_ADDRESS));
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 (EFI_DHCP4_CONFIG_DATA));
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 DHCP_PROTOCOL *Instance;
254
255 Instance = DhcpSb->ActiveChild;
256 Config = &DhcpSb->ActiveConfig;
257
258 DhcpSb->ServiceState = DHCP_UNCONFIGED;
259 DhcpSb->ActiveChild = NULL;
260
261 if (Config->DiscoverTimeout != NULL) {
262 NetFreePool (Config->DiscoverTimeout);
263
264 Config->DiscoverTryCount = 0;
265 Config->DiscoverTimeout = NULL;
266 }
267
268 if (Config->RequestTimeout != NULL) {
269 NetFreePool (Config->RequestTimeout);
270
271 Config->RequestTryCount = 0;
272 Config->RequestTimeout = NULL;
273 }
274
275 Config->Dhcp4Callback = NULL;
276 Config->CallbackContext = NULL;
277 }
278
279
280 /**
281 Configure the DHCP protocol instance and its underlying DHCP service
282 for operation. If Dhcp4CfgData is NULL and the child is currently
283 controlling the DHCP service, release the control.
284
285 @param This The DHCP protocol instance
286 @param Dhcp4CfgData The DHCP configure data.
287
288 @retval EFI_INVALID_PARAMETER The parameters are invalid.
289 @retval EFI_ACCESS_DENIED The service isn't in one of configurable states,
290 or there is already an active child.
291 @retval EFI_OUT_OF_RESOURCE Failed to allocate some resources.
292 @retval EFI_SUCCESS The child is configured.
293
294 **/
295 STATIC
296 EFI_STATUS
297 EFIAPI
298 EfiDhcp4Configure (
299 IN EFI_DHCP4_PROTOCOL *This,
300 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL
301 )
302 {
303 EFI_DHCP4_CONFIG_DATA *Config;
304 DHCP_PROTOCOL *Instance;
305 DHCP_SERVICE *DhcpSb;
306 EFI_STATUS Status;
307 EFI_TPL OldTpl;
308 UINT32 Index;
309 IP4_ADDR Ip;
310
311 //
312 // First validate the parameters
313 //
314 if (This == NULL) {
315 return EFI_INVALID_PARAMETER;
316 }
317
318 if (Dhcp4CfgData != NULL) {
319 if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {
320 return EFI_INVALID_PARAMETER;
321 }
322
323 if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {
324 return EFI_INVALID_PARAMETER;
325 }
326
327 if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {
328 return EFI_INVALID_PARAMETER;
329 }
330
331 NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));
332
333 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {
334
335 return EFI_INVALID_PARAMETER;
336 }
337 }
338
339 Instance = DHCP_INSTANCE_FROM_THIS (This);
340
341 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
342 return EFI_INVALID_PARAMETER;
343 }
344
345 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
346
347 DhcpSb = Instance->Service;
348 Config = &DhcpSb->ActiveConfig;
349
350 Status = EFI_ACCESS_DENIED;
351
352 if ((DhcpSb->DhcpState != Dhcp4Stopped) &&
353 (DhcpSb->DhcpState != Dhcp4Init) &&
354 (DhcpSb->DhcpState != Dhcp4InitReboot) &&
355 (DhcpSb->DhcpState != Dhcp4Bound)) {
356
357 goto ON_EXIT;
358 }
359
360 if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {
361 goto ON_EXIT;
362 }
363
364 if (Dhcp4CfgData != NULL) {
365 Status = EFI_OUT_OF_RESOURCES;
366 DhcpCleanConfigure (Config);
367
368 if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {
369 goto ON_EXIT;
370 }
371
372 DhcpSb->UserOptionLen = 0;
373
374 for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {
375 DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;
376 }
377
378 DhcpSb->ActiveChild = Instance;
379
380 if (DhcpSb->DhcpState == Dhcp4Stopped) {
381 DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);
382
383 if (DhcpSb->ClientAddr != 0) {
384 DhcpSb->DhcpState = Dhcp4InitReboot;
385 } else {
386 DhcpSb->DhcpState = Dhcp4Init;
387 }
388 }
389
390 DhcpSb->ServiceState = DHCP_CONFIGED;
391 Status = EFI_SUCCESS;
392
393 } else if (DhcpSb->ActiveChild == Instance) {
394 Status = EFI_SUCCESS;
395 DhcpYieldControl (DhcpSb);
396 }
397
398 ON_EXIT:
399 NET_RESTORE_TPL (OldTpl);
400 return Status;
401 }
402
403
404 /**
405 Start the DHCP process.
406
407 @param This The DHCP protocol instance
408 @param CompletionEvent The event to signal is address is acquired.
409
410 @retval EFI_INVALID_PARAMETER The parameters are invalid.
411 @retval EFI_NOT_STARTED The protocol hasn't been configured.
412 @retval EFI_ALREADY_STARTED The DHCP process has already been started.
413 @retval EFI_SUCCESS The DHCP process is started.
414
415 **/
416 STATIC
417 EFI_STATUS
418 EFIAPI
419 EfiDhcp4Start (
420 IN EFI_DHCP4_PROTOCOL *This,
421 IN EFI_EVENT CompletionEvent OPTIONAL
422 )
423 {
424 DHCP_PROTOCOL *Instance;
425 DHCP_SERVICE *DhcpSb;
426 EFI_STATUS Status;
427 EFI_TPL OldTpl;
428
429 //
430 // First validate the parameters
431 //
432 if (This == NULL) {
433 return EFI_INVALID_PARAMETER;
434 }
435
436 Instance = DHCP_INSTANCE_FROM_THIS (This);
437
438 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
439 return EFI_INVALID_PARAMETER;
440 }
441
442 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
443 DhcpSb = Instance->Service;
444
445 if (DhcpSb->DhcpState == Dhcp4Stopped) {
446 Status = EFI_NOT_STARTED;
447 goto ON_ERROR;
448 }
449
450 if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {
451 Status = EFI_ALREADY_STARTED;
452 goto ON_ERROR;
453 }
454
455 DhcpSb->IoStatus = EFI_ALREADY_STARTED;
456
457 if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {
458 goto ON_ERROR;
459 }
460
461 //
462 // Start/Restart the receiving.
463 //
464 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);
465
466 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
467 goto ON_ERROR;
468 }
469
470 Instance->CompletionEvent = CompletionEvent;
471
472 //
473 // Restore the TPL now, don't call poll function at NET_TPL_LOCK.
474 //
475 NET_RESTORE_TPL (OldTpl);
476
477 if (CompletionEvent == NULL) {
478 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
479 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);
480 }
481
482 return DhcpSb->IoStatus;
483 }
484
485 return EFI_SUCCESS;
486
487 ON_ERROR:
488 NET_RESTORE_TPL (OldTpl);
489 return Status;
490 }
491
492
493 /**
494 Request an extra manual renew/rebind.
495
496 @param This The DHCP protocol instance
497 @param RebindRequest TRUE if request a rebind, otherwise renew it
498 @param CompletionEvent Event to signal when complete
499
500 @retval EFI_INVALID_PARAMETER The parameters are invalid
501 @retval EFI_NOT_STARTED The DHCP protocol hasn't been started.
502 @retval EFI_ACCESS_DENIED The DHCP protocol isn't in Bound state.
503 @retval EFI_SUCCESS The DHCP is renewed/rebound.
504
505 **/
506 STATIC
507 EFI_STATUS
508 EFIAPI
509 EfiDhcp4RenewRebind (
510 IN EFI_DHCP4_PROTOCOL *This,
511 IN BOOLEAN RebindRequest,
512 IN EFI_EVENT CompletionEvent OPTIONAL
513 )
514 {
515 DHCP_PROTOCOL *Instance;
516 DHCP_SERVICE *DhcpSb;
517 EFI_STATUS Status;
518 EFI_TPL OldTpl;
519
520 //
521 // First validate the parameters
522 //
523 if (This == NULL) {
524 return EFI_INVALID_PARAMETER;
525 }
526
527 Instance = DHCP_INSTANCE_FROM_THIS (This);
528
529 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
530 return EFI_INVALID_PARAMETER;
531 }
532
533 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
534 DhcpSb = Instance->Service;
535
536 if (DhcpSb->DhcpState == Dhcp4Stopped) {
537 Status = EFI_NOT_STARTED;
538 goto ON_ERROR;
539 }
540
541 if (DhcpSb->DhcpState != Dhcp4Bound) {
542 Status = EFI_ACCESS_DENIED;
543 goto ON_ERROR;
544 }
545
546 if (DHCP_IS_BOOTP (DhcpSb->Para)) {
547 return EFI_SUCCESS;
548 }
549
550 //
551 // Transit the states then send a extra DHCP request
552 //
553 if (!RebindRequest) {
554 DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);
555 } else {
556 DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);
557 }
558
559 Status = DhcpSendMessage (
560 DhcpSb,
561 DhcpSb->Selected,
562 DhcpSb->Para,
563 DHCP_MSG_REQUEST,
564 "Extra renew/rebind by the application"
565 );
566
567 if (EFI_ERROR (Status)) {
568 DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);
569 goto ON_ERROR;
570 }
571
572 DhcpSb->ExtraRefresh = TRUE;
573 DhcpSb->IoStatus = EFI_ALREADY_STARTED;
574 Instance->RenewRebindEvent = CompletionEvent;
575
576 NET_RESTORE_TPL (OldTpl);
577
578 if (CompletionEvent == NULL) {
579 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {
580 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);
581 }
582
583 return DhcpSb->IoStatus;
584 }
585
586 return EFI_SUCCESS;
587
588 ON_ERROR:
589 NET_RESTORE_TPL (OldTpl);
590 return Status;
591 }
592
593
594 /**
595 Release the current acquired lease.
596
597 @param This The DHCP protocol instance
598
599 @retval EFI_INVALID_PARAMETER The parameter is invalid
600 @retval EFI_DEVICE_ERROR Failed to transmit the DHCP release packet
601 @retval EFI_ACCESS_DENIED The DHCP service isn't in one of the connected
602 state.
603 @retval EFI_SUCCESS The lease is released.
604
605 **/
606 STATIC
607 EFI_STATUS
608 EFIAPI
609 EfiDhcp4Release (
610 IN EFI_DHCP4_PROTOCOL *This
611 )
612 {
613 DHCP_PROTOCOL *Instance;
614 DHCP_SERVICE *DhcpSb;
615 EFI_STATUS Status;
616 EFI_TPL OldTpl;
617
618 //
619 // First validate the parameters
620 //
621 if (This == NULL) {
622 return EFI_INVALID_PARAMETER;
623 }
624
625 Instance = DHCP_INSTANCE_FROM_THIS (This);
626
627 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
628 return EFI_INVALID_PARAMETER;
629 }
630
631 Status = EFI_SUCCESS;
632 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
633 DhcpSb = Instance->Service;
634
635 if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {
636 Status = EFI_ACCESS_DENIED;
637 goto ON_EXIT;
638 }
639
640 if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {
641 Status = DhcpSendMessage (
642 DhcpSb,
643 DhcpSb->Selected,
644 DhcpSb->Para,
645 DHCP_MSG_RELEASE,
646 NULL
647 );
648
649 if (EFI_ERROR (Status)) {
650 Status = EFI_DEVICE_ERROR;
651 goto ON_EXIT;
652 }
653 }
654
655 DhcpCleanLease (DhcpSb);
656
657 ON_EXIT:
658 NET_RESTORE_TPL (OldTpl);
659 return Status;
660 }
661
662
663 /**
664 Stop the current DHCP process. After this, other DHCP child
665 can gain control of the service, configure and use it.
666
667 @param This The DHCP protocol instance
668
669 @retval EFI_INVALID_PARAMETER The parameter is invalid.
670 @retval EFI_SUCCESS The DHCP process is stopped.
671
672 **/
673 STATIC
674 EFI_STATUS
675 EFIAPI
676 EfiDhcp4Stop (
677 IN EFI_DHCP4_PROTOCOL *This
678 )
679 {
680 DHCP_PROTOCOL *Instance;
681 DHCP_SERVICE *DhcpSb;
682 EFI_TPL OldTpl;
683
684 //
685 // First validate the parameters
686 //
687 if (This == NULL) {
688 return EFI_INVALID_PARAMETER;
689 }
690
691 Instance = DHCP_INSTANCE_FROM_THIS (This);
692
693 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {
694 return EFI_INVALID_PARAMETER;
695 }
696
697 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);
698 DhcpSb = Instance->Service;
699
700 DhcpCleanLease (DhcpSb);
701
702 DhcpSb->DhcpState = Dhcp4Stopped;
703 DhcpSb->ServiceState = DHCP_UNCONFIGED;
704
705 NET_RESTORE_TPL (OldTpl);
706 return EFI_SUCCESS;
707 }
708
709
710 /**
711 Build a new DHCP packet from the seed packet. Options may be deleted or
712 appended. The caller should free the NewPacket when finished using it.
713
714 @param This The DHCP protocol instance.
715 @param SeedPacket The seed packet to start with
716 @param DeleteCount The number of options to delete
717 @param DeleteList The options to delete from the packet
718 @param AppendCount The number of options to append
719 @param AppendList The options to append to the packet
720 @param NewPacket The new packet, allocated and built by this
721 function.
722
723 @retval EFI_INVALID_PARAMETER The parameters are invalid.
724 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory
725 @retval EFI_SUCCESS The packet is build.
726
727 **/
728 STATIC
729 EFI_STATUS
730 EFIAPI
731 EfiDhcp4Build (
732 IN EFI_DHCP4_PROTOCOL *This,
733 IN EFI_DHCP4_PACKET *SeedPacket,
734 IN UINT32 DeleteCount,
735 IN UINT8 *DeleteList OPTIONAL,
736 IN UINT32 AppendCount,
737 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,
738 OUT EFI_DHCP4_PACKET **NewPacket
739 )
740 {
741 //
742 // First validate the parameters
743 //
744 if ((This == NULL) || (NewPacket == NULL)) {
745 return EFI_INVALID_PARAMETER;
746 }
747
748 if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
749 EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {
750
751 return EFI_INVALID_PARAMETER;
752 }
753
754 if (((DeleteCount == 0) && (AppendCount == 0)) ||
755 ((DeleteCount != 0) && (DeleteList == NULL)) ||
756 ((AppendCount != 0) && (AppendList == NULL))) {
757
758 return EFI_INVALID_PARAMETER;
759 }
760
761 return DhcpBuild (
762 SeedPacket,
763 DeleteCount,
764 DeleteList,
765 AppendCount,
766 AppendList,
767 NewPacket
768 );
769 }
770
771
772 /**
773 Transmit and receive a packet through this DHCP service.
774 This is unsupported.
775
776 @param This The DHCP protocol instance
777 @param Token The transmit and receive instance
778
779 @retval EFI_UNSUPPORTED It always returns unsupported.
780
781 **/
782 STATIC
783 EFI_STATUS
784 EFIAPI
785 EfiDhcp4TransmitReceive (
786 IN EFI_DHCP4_PROTOCOL *This,
787 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token
788 )
789 {
790 //
791 // This function is for PXE, leave it for now
792 //
793 return EFI_UNSUPPORTED;
794 }
795
796
797 /**
798 Callback function for DhcpIterateOptions. This callback sets the
799 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point
800 the individual DHCP option in the packet.
801
802 @param Tag The DHCP option type
803 @param Len length of the DHCP option data
804 @param Data The DHCP option data
805 @param Context The context, to pass several parameters in.
806
807 @retval EFI_SUCCESS It always returns EFI_SUCCESS
808
809 **/
810 STATIC
811 EFI_STATUS
812 Dhcp4ParseCheckOption (
813 IN UINT8 Tag,
814 IN UINT8 Len,
815 IN UINT8 *Data,
816 IN VOID *Context
817 )
818 {
819 DHCP_PARSE_CONTEXT *Parse;
820
821 Parse = (DHCP_PARSE_CONTEXT *) Context;
822 Parse->Index++;
823
824 if (Parse->Index < Parse->OptionCount) {
825 //
826 // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for
827 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only
828 // pass in the point to option data.
829 //
830 Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);
831 }
832
833 return EFI_SUCCESS;
834 }
835
836
837 /**
838 Parse the DHCP options in the Packet into the PacketOptionList.
839 User should allocate this array of EFI_DHCP4_PACKET_OPTION points.
840
841 @param This The DHCP protocol instance
842 @param Packet The DHCP packet to parse
843 @param OptionCount On input, the size of the PacketOptionList; On
844 output, the actual number of options processed.
845 @param PacketOptionList The array of EFI_DHCP4_PACKET_OPTION points
846
847 @retval EFI_INVALID_PARAMETER The parameters are invalid.
848 @retval EFI_BUFFER_TOO_SMALL A bigger array of points is needed.
849 @retval EFI_SUCCESS The options are parsed.
850
851 **/
852 STATIC
853 EFI_STATUS
854 EFIAPI
855 EfiDhcp4Parse (
856 IN EFI_DHCP4_PROTOCOL *This,
857 IN EFI_DHCP4_PACKET *Packet,
858 IN OUT UINT32 *OptionCount,
859 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL
860 )
861 {
862 DHCP_PARSE_CONTEXT Context;
863 EFI_STATUS Status;
864
865 //
866 // First validate the parameters
867 //
868 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {
869 return EFI_INVALID_PARAMETER;
870 }
871
872 if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||
873 (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||
874 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {
875
876 return EFI_INVALID_PARAMETER;
877 }
878
879 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {
880 return EFI_BUFFER_TOO_SMALL;
881 }
882
883 NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));
884
885 Context.Option = PacketOptionList;
886 Context.OptionCount = *OptionCount;
887 Context.Index = 0;
888
889 Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);
890
891 if (EFI_ERROR (Status)) {
892 return Status;
893 }
894
895 *OptionCount = Context.Index;
896
897 if (Context.Index > Context.OptionCount) {
898 return EFI_BUFFER_TOO_SMALL;
899 }
900
901 return EFI_SUCCESS;
902 }
903
904 EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {
905 EfiDhcp4GetModeData,
906 EfiDhcp4Configure,
907 EfiDhcp4Start,
908 EfiDhcp4RenewRebind,
909 EfiDhcp4Release,
910 EfiDhcp4Stop,
911 EfiDhcp4Build,
912 EfiDhcp4TransmitReceive,
913 EfiDhcp4Parse
914 };