TianoCore EDK2 master
Loading...
Searching...
No Matches
HttpBootDhcp6.c
Go to the documentation of this file.
1
10#include "HttpBootDxe.h"
11
22UINT32
26 IN UINT8 *Buffer
27 )
28{
30 UINT16 Value;
31 UINT32 Index;
32
33 Index = 0;
34 OptList[0] = (EFI_DHCP6_PACKET_OPTION *)Buffer;
35
36 //
37 // Append client option request option
38 //
39 OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO);
40 OptList[Index]->OpLen = HTONS (8);
41 OptEnt.Oro = (HTTP_BOOT_DHCP6_OPTION_ORO *)OptList[Index]->Data;
42 OptEnt.Oro->OpCode[0] = HTONS (DHCP6_OPT_BOOT_FILE_URL);
43 OptEnt.Oro->OpCode[1] = HTONS (DHCP6_OPT_BOOT_FILE_PARAM);
44 OptEnt.Oro->OpCode[2] = HTONS (DHCP6_OPT_DNS_SERVERS);
45 OptEnt.Oro->OpCode[3] = HTONS (DHCP6_OPT_VENDOR_CLASS);
46 Index++;
47 OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);
48
49 //
50 // Append client network device interface option
51 //
52 OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI);
53 OptList[Index]->OpLen = HTONS ((UINT16)3);
54 OptEnt.Undi = (HTTP_BOOT_DHCP6_OPTION_UNDI *)OptList[Index]->Data;
55
56 if (Private->Nii != NULL) {
57 OptEnt.Undi->Type = Private->Nii->Type;
58 OptEnt.Undi->MajorVer = Private->Nii->MajorVer;
59 OptEnt.Undi->MinorVer = Private->Nii->MinorVer;
60 } else {
61 OptEnt.Undi->Type = DEFAULT_UNDI_TYPE;
62 OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR;
63 OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR;
64 }
65
66 Index++;
67 OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);
68
69 //
70 // Append client system architecture option
71 //
72 OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH);
73 OptList[Index]->OpLen = HTONS ((UINT16)sizeof (HTTP_BOOT_DHCP6_OPTION_ARCH));
74 OptEnt.Arch = (HTTP_BOOT_DHCP6_OPTION_ARCH *)OptList[Index]->Data;
75 Value = HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE);
76 CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16));
77 Index++;
78 OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);
79
80 //
81 // Append vendor class identify option.
82 //
83 OptList[Index]->OpCode = HTONS (DHCP6_OPT_VENDOR_CLASS);
84 OptList[Index]->OpLen = HTONS ((UINT16)sizeof (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS));
85 OptEnt.VendorClass = (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS *)OptList[Index]->Data;
86 OptEnt.VendorClass->Vendor = HTONL (HTTP_BOOT_DHCP6_ENTERPRISE_NUM);
87 OptEnt.VendorClass->ClassLen = HTONS ((UINT16)sizeof (HTTP_BOOT_CLASS_ID));
88 CopyMem (
89 &OptEnt.VendorClass->ClassId,
90 DEFAULT_CLASS_ID_DATA,
91 sizeof (HTTP_BOOT_CLASS_ID)
92 );
94 EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE,
95 OptEnt.VendorClass->ClassId.ArchitectureType,
96 sizeof (OptEnt.VendorClass->ClassId.ArchitectureType)
97 );
98
99 if (Private->Nii != NULL) {
100 CopyMem (
101 OptEnt.VendorClass->ClassId.InterfaceName,
102 Private->Nii->StringId,
103 sizeof (OptEnt.VendorClass->ClassId.InterfaceName)
104 );
106 Private->Nii->MajorVer,
107 OptEnt.VendorClass->ClassId.UndiMajor,
108 sizeof (OptEnt.VendorClass->ClassId.UndiMajor)
109 );
111 Private->Nii->MinorVer,
112 OptEnt.VendorClass->ClassId.UndiMinor,
113 sizeof (OptEnt.VendorClass->ClassId.UndiMinor)
114 );
115 }
116
117 Index++;
118
119 return Index;
120}
121
135 IN UINT8 *Buffer,
136 IN UINT32 Length,
137 IN UINT16 OptTag
138 )
139{
141 UINT32 Offset;
142
143 Option = (EFI_DHCP6_PACKET_OPTION *)Buffer;
144 Offset = 0;
145
146 //
147 // OpLen and OpCode here are both stored in network order.
148 //
149 while (Offset < Length) {
150 if (NTOHS (Option->OpCode) == OptTag) {
151 return Option;
152 }
153
154 Offset += (NTOHS (Option->OpLen) + 4);
155 Option = (EFI_DHCP6_PACKET_OPTION *)(Buffer + Offset);
156 }
157
158 return NULL;
159}
160
173 )
174{
175 EFI_DHCP6_PACKET *Offer;
176 EFI_DHCP6_PACKET_OPTION **Options;
178 HTTP_BOOT_OFFER_TYPE OfferType;
179 EFI_IPv6_ADDRESS IpAddr;
180 BOOLEAN IsProxyOffer;
181 BOOLEAN IsHttpOffer;
182 BOOLEAN IsDnsOffer;
183 BOOLEAN IpExpressedUri;
184 EFI_STATUS Status;
185 UINT32 Offset;
186 UINT32 Length;
187
188 IsDnsOffer = FALSE;
189 IpExpressedUri = FALSE;
190 IsProxyOffer = TRUE;
191 IsHttpOffer = FALSE;
192 Offer = &Cache6->Packet.Offer;
193 Options = Cache6->OptList;
194
195 ZeroMem (Cache6->OptList, sizeof (Cache6->OptList));
196
197 Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option);
198 Offset = 0;
199 Length = GET_DHCP6_OPTION_SIZE (Offer);
200
201 //
202 // OpLen and OpCode here are both stored in network order, since they are from original packet.
203 //
204 while (Offset < Length) {
205 if (NTOHS (Option->OpCode) == DHCP6_OPT_IA_NA) {
206 Options[HTTP_BOOT_DHCP6_IDX_IA_NA] = Option;
207 } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_URL) {
208 //
209 // The server sends this option to inform the client about an URL to a boot file.
210 //
211 Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] = Option;
212 } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_PARAM) {
213 Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_PARAM] = Option;
214 } else if (NTOHS (Option->OpCode) == DHCP6_OPT_VENDOR_CLASS) {
215 Options[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS] = Option;
216 } else if (NTOHS (Option->OpCode) == DHCP6_OPT_DNS_SERVERS) {
217 Options[HTTP_BOOT_DHCP6_IDX_DNS_SERVER] = Option;
218 }
219
220 Offset += (NTOHS (Option->OpLen) + 4);
221 Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option + Offset);
222 }
223
224 //
225 // The offer with assigned client address is NOT a proxy offer.
226 // An ia_na option, embedded with valid ia_addr option and a status_code of success.
227 //
228 Option = Options[HTTP_BOOT_DHCP6_IDX_IA_NA];
229 if (Option != NULL) {
231 Option->Data + 12,
232 NTOHS (Option->OpLen),
233 DHCP6_OPT_STATUS_CODE
234 );
235 if (((Option != NULL) && (Option->Data[0] == 0)) || (Option == NULL)) {
236 IsProxyOffer = FALSE;
237 }
238 }
239
240 //
241 // The offer with "HTTPClient" is a Http offer.
242 //
243 Option = Options[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS];
244
245 if ((Option != NULL) &&
246 (NTOHS (Option->OpLen) >= 16) &&
247 (CompareMem ((Option->Data + 6), DEFAULT_CLASS_ID_DATA, 10) == 0))
248 {
249 IsHttpOffer = TRUE;
250 }
251
252 //
253 // The offer with Domain Server is a DNS offer.
254 //
255 Option = Options[HTTP_BOOT_DHCP6_IDX_DNS_SERVER];
256 if (Option != NULL) {
257 IsDnsOffer = TRUE;
258 }
259
260 //
261 // Http offer must have a boot URI.
262 //
263 if (IsHttpOffer && (Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] == NULL)) {
264 return EFI_DEVICE_ERROR;
265 }
266
267 //
268 // Try to retrieve the IP of HTTP server from URI.
269 //
270 if (IsHttpOffer) {
271 Status = HttpParseUrl (
272 (CHAR8 *)Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,
273 (UINT32)AsciiStrLen ((CHAR8 *)Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data),
274 FALSE,
275 &Cache6->UriParser
276 );
277 if (EFI_ERROR (Status)) {
278 return EFI_DEVICE_ERROR;
279 }
280
281 Status = HttpUrlGetIp6 (
282 (CHAR8 *)Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,
283 Cache6->UriParser,
284 &IpAddr
285 );
286 IpExpressedUri = !EFI_ERROR (Status);
287 }
288
289 //
290 // Determine offer type of the DHCPv6 packet.
291 //
292 if (IsHttpOffer) {
293 if (IpExpressedUri) {
294 if (IsProxyOffer) {
295 OfferType = HttpOfferTypeProxyIpUri;
296 } else {
297 OfferType = IsDnsOffer ? HttpOfferTypeDhcpIpUriDns : HttpOfferTypeDhcpIpUri;
298 }
299 } else {
300 if (!IsProxyOffer) {
301 OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns : HttpOfferTypeDhcpNameUri;
302 } else {
303 OfferType = HttpOfferTypeProxyNameUri;
304 }
305 }
306 } else {
307 if (!IsProxyOffer) {
308 OfferType = IsDnsOffer ? HttpOfferTypeDhcpDns : HttpOfferTypeDhcpOnly;
309 } else {
310 return EFI_DEVICE_ERROR;
311 }
312 }
313
314 Cache6->OfferType = OfferType;
315 return EFI_SUCCESS;
316}
317
330 IN EFI_DHCP6_PACKET *Dst,
332 )
333{
334 if (Dst->Size < Src->Length) {
335 return EFI_BUFFER_TOO_SMALL;
336 }
337
338 CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length);
339 Dst->Length = Src->Length;
340
341 return EFI_SUCCESS;
342}
343
356 IN HTTP_BOOT_PRIVATE_DATA *Private,
357 IN EFI_DHCP6_PACKET *RcvdOffer
358 )
359{
361 EFI_DHCP6_PACKET *Offer;
362 HTTP_BOOT_OFFER_TYPE OfferType;
363 EFI_STATUS Status;
364
365 Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6;
366 Offer = &Cache6->Packet.Offer;
367
368 //
369 // Cache the content of DHCPv6 packet firstly.
370 //
371 Status = HttpBootCacheDhcp6Packet (Offer, RcvdOffer);
372 if (EFI_ERROR (Status)) {
373 return Status;
374 }
375
376 //
377 // Validate the DHCPv6 packet, and parse the options and offer type.
378 //
379 if (EFI_ERROR (HttpBootParseDhcp6Packet (Cache6))) {
380 return EFI_ABORTED;
381 }
382
383 //
384 // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.
385 //
386 OfferType = Cache6->OfferType;
387 ASSERT (OfferType < HttpOfferTypeMax);
388 ASSERT (Private->OfferCount[OfferType] < HTTP_BOOT_OFFER_MAX_NUM);
389 Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;
390 Private->OfferCount[OfferType]++;
391 Private->OfferNum++;
392
393 return EFI_SUCCESS;
394}
395
416EFIAPI
419 IN VOID *Context,
420 IN EFI_DHCP6_STATE CurrentState,
421 IN EFI_DHCP6_EVENT Dhcp6Event,
422 IN EFI_DHCP6_PACKET *Packet,
423 OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL
424 )
425{
426 HTTP_BOOT_PRIVATE_DATA *Private;
427 EFI_DHCP6_PACKET *SelectAd;
428 EFI_STATUS Status;
429 BOOLEAN Received;
430
431 if ((Dhcp6Event != Dhcp6SendSolicit) &&
432 (Dhcp6Event != Dhcp6RcvdAdvertise) &&
433 (Dhcp6Event != Dhcp6SendRequest) &&
434 (Dhcp6Event != Dhcp6RcvdReply) &&
435 (Dhcp6Event != Dhcp6SelectAdvertise))
436 {
437 return EFI_SUCCESS;
438 }
439
440 ASSERT (Packet != NULL);
441
442 Private = (HTTP_BOOT_PRIVATE_DATA *)Context;
443 Status = EFI_SUCCESS;
444 if ((Private->HttpBootCallback != NULL) && (Dhcp6Event != Dhcp6SelectAdvertise)) {
445 Received = (BOOLEAN)(Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply);
446 Status = Private->HttpBootCallback->Callback (
447 Private->HttpBootCallback,
449 Received,
450 Packet->Length,
451 &Packet->Dhcp6
452 );
453 if (EFI_ERROR (Status)) {
454 return EFI_ABORTED;
455 }
456 }
457
458 switch (Dhcp6Event) {
460 Status = EFI_NOT_READY;
461 if (Packet->Length > HTTP_BOOT_DHCP6_PACKET_MAX_SIZE) {
462 //
463 // Ignore the incoming packets which exceed the maximum length.
464 //
465 break;
466 }
467
468 if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) {
469 //
470 // Cache the dhcp offers to OfferBuffer[] for select later, and record
471 // the OfferIndex and OfferCount.
472 // If error happens, just ignore this packet and continue to wait more offer.
473 //
474 HttpBootCacheDhcp6Offer (Private, Packet);
475 }
476
477 break;
478
480 //
481 // Select offer by the default policy or by order, and record the SelectIndex
482 // and SelectProxyType.
483 //
484 HttpBootSelectDhcpOffer (Private);
485
486 if (Private->SelectIndex == 0) {
487 Status = EFI_ABORTED;
488 } else {
489 ASSERT (NewPacket != NULL);
490 SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;
491 *NewPacket = AllocateZeroPool (SelectAd->Size);
492 if (*NewPacket == NULL) {
493 return EFI_OUT_OF_RESOURCES;
494 }
495
496 CopyMem (*NewPacket, SelectAd, SelectAd->Size);
497 }
498
499 break;
500
501 default:
502 break;
503 }
504
505 return Status;
506}
507
525 IN HTTP_BOOT_PRIVATE_DATA *Private,
526 IN UINTN TimeOutInSecond,
527 OUT EFI_IPv6_ADDRESS *GatewayAddr
528 )
529{
530 EFI_STATUS Status;
531 EFI_IP6_PROTOCOL *Ip6;
532 EFI_IP6_MODE_DATA Ip6ModeData;
533 UINTN Index;
534 EFI_EVENT TimeOutEvt;
535 UINTN RetryCount;
536 BOOLEAN GatewayIsFound;
537
538 ASSERT (GatewayAddr != NULL);
539 ASSERT (Private != NULL);
540
541 Ip6 = Private->Ip6;
542 GatewayIsFound = FALSE;
543 RetryCount = 0;
544 TimeOutEvt = NULL;
545 Status = EFI_SUCCESS;
546 ZeroMem (GatewayAddr, sizeof (EFI_IPv6_ADDRESS));
547
548 while (TRUE) {
549 Status = Ip6->GetModeData (Ip6, &Ip6ModeData, NULL, NULL);
550 if (EFI_ERROR (Status)) {
551 goto ON_EXIT;
552 }
553
554 //
555 // Find out the gateway address which can route the message which send to ServerIp.
556 //
557 for (Index = 0; Index < Ip6ModeData.RouteCount; Index++) {
558 if (NetIp6IsNetEqual (&Private->ServerIp.v6, &Ip6ModeData.RouteTable[Index].Destination, Ip6ModeData.RouteTable[Index].PrefixLength)) {
559 IP6_COPY_ADDRESS (GatewayAddr, &Ip6ModeData.RouteTable[Index].Gateway);
560 GatewayIsFound = TRUE;
561 break;
562 }
563 }
564
565 if (Ip6ModeData.AddressList != NULL) {
566 FreePool (Ip6ModeData.AddressList);
567 }
568
569 if (Ip6ModeData.GroupTable != NULL) {
570 FreePool (Ip6ModeData.GroupTable);
571 }
572
573 if (Ip6ModeData.RouteTable != NULL) {
574 FreePool (Ip6ModeData.RouteTable);
575 }
576
577 if (Ip6ModeData.NeighborCache != NULL) {
578 FreePool (Ip6ModeData.NeighborCache);
579 }
580
581 if (Ip6ModeData.PrefixTable != NULL) {
582 FreePool (Ip6ModeData.PrefixTable);
583 }
584
585 if (Ip6ModeData.IcmpTypeList != NULL) {
586 FreePool (Ip6ModeData.IcmpTypeList);
587 }
588
589 if (GatewayIsFound || (RetryCount == TimeOutInSecond)) {
590 break;
591 }
592
593 RetryCount++;
594
595 //
596 // Delay 1 second then recheck it again.
597 //
598 if (TimeOutEvt == NULL) {
599 Status = gBS->CreateEvent (
600 EVT_TIMER,
601 TPL_CALLBACK,
602 NULL,
603 NULL,
604 &TimeOutEvt
605 );
606 if (EFI_ERROR (Status)) {
607 goto ON_EXIT;
608 }
609 }
610
611 Status = gBS->SetTimer (TimeOutEvt, TimerRelative, TICKS_PER_SECOND);
612 if (EFI_ERROR (Status)) {
613 goto ON_EXIT;
614 }
615
616 while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
617 Ip6->Poll (Ip6);
618 }
619 }
620
621ON_EXIT:
622 if (TimeOutEvt != NULL) {
623 gBS->CloseEvent (TimeOutEvt);
624 }
625
626 if (GatewayIsFound) {
627 Status = EFI_SUCCESS;
628 } else if (RetryCount == TimeOutInSecond) {
629 Status = EFI_TIMEOUT;
630 }
631
632 return Status;
633}
634
647 )
648{
650 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
651 EFI_STATUS Status;
652 UINTN DataSize;
653
654 Ip6Config = Private->Ip6Config;
655 DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
656
657 //
658 // Get and store the current policy of IP6 driver.
659 //
660 Status = Ip6Config->GetData (
661 Ip6Config,
663 &DataSize,
664 &Policy
665 );
666 if (EFI_ERROR (Status)) {
667 return Status;
668 }
669
670 if (Policy == Ip6ConfigPolicyManual) {
672 Status = Ip6Config->SetData (
673 Ip6Config,
675 sizeof (EFI_IP6_CONFIG_POLICY),
676 &Policy
677 );
678 if (EFI_ERROR (Status)) {
679 return Status;
680 }
681 }
682
683 return EFI_SUCCESS;
684}
685
700 IN HTTP_BOOT_PRIVATE_DATA *Private,
701 IN UINTN DataLength,
702 IN VOID *DnsServerData
703 )
704{
705 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
706
707 ASSERT (Private->UsingIpv6);
708
709 Ip6Config = Private->Ip6Config;
710
711 return Ip6Config->SetData (
712 Ip6Config,
714 DataLength,
715 DnsServerData
716 );
717}
718
731 )
732{
733 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;
734 EFI_STATUS Status;
735
736 ASSERT (Private->UsingIpv6);
737 Ip6Config = Private->Ip6Config;
738
739 //
740 // Set the default gateway address.
741 //
742 if (!Private->NoGateway && !NetIp6IsUnspecifiedAddr (&Private->GatewayIp.v6)) {
743 Status = Ip6Config->SetData (
744 Ip6Config,
746 sizeof (EFI_IPv6_ADDRESS),
747 &Private->GatewayIp.v6
748 );
749 if (EFI_ERROR (Status)) {
750 return Status;
751 }
752 }
753
754 return EFI_SUCCESS;
755}
756
769 )
770{
771 EFI_STATUS Status;
772 EFI_IP6_PROTOCOL *Ip6;
776 EFI_IPv6_ADDRESS *Ip6Addr;
777 EFI_IPv6_ADDRESS GatewayAddr;
778 EFI_IP6_CONFIG_DATA Ip6CfgData;
779 EFI_EVENT MappedEvt;
780 UINTN DataSize;
781 BOOLEAN IsAddressOk;
782 UINTN Index;
783
784 ASSERT (Private->UsingIpv6);
785
786 MappedEvt = NULL;
787 IsAddressOk = FALSE;
788 Ip6Addr = NULL;
789 Ip6Cfg = Private->Ip6Config;
790 Ip6 = Private->Ip6;
791
792 ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
793 CopyMem (&CfgAddr, &Private->StationIp.v6, sizeof (EFI_IPv6_ADDRESS));
794 ZeroMem (&Ip6CfgData, sizeof (EFI_IP6_CONFIG_DATA));
795
796 Ip6CfgData.AcceptIcmpErrors = TRUE;
797 Ip6CfgData.DefaultProtocol = IP6_ICMP;
798 Ip6CfgData.HopLimit = HTTP_BOOT_DEFAULT_HOPLIMIT;
799 Ip6CfgData.ReceiveTimeout = HTTP_BOOT_DEFAULT_LIFETIME;
800 Ip6CfgData.TransmitTimeout = HTTP_BOOT_DEFAULT_LIFETIME;
801
802 Status = Ip6->Configure (Ip6, &Ip6CfgData);
803 if (EFI_ERROR (Status)) {
804 goto ON_EXIT;
805 }
806
807 //
808 // Retrieve the gateway address from IP6 route table.
809 //
810 Status = HttpBootCheckRouteTable (Private, HTTP_BOOT_IP6_ROUTE_TABLE_TIMEOUT, &GatewayAddr);
811 if (EFI_ERROR (Status)) {
812 Private->NoGateway = TRUE;
813 } else {
814 IP6_COPY_ADDRESS (&Private->GatewayIp.v6, &GatewayAddr);
815 }
816
817 //
818 // Set the new address by Ip6ConfigProtocol manually.
819 //
820 Policy = Ip6ConfigPolicyManual;
821 Status = Ip6Cfg->SetData (
822 Ip6Cfg,
824 sizeof (EFI_IP6_CONFIG_POLICY),
825 &Policy
826 );
827 if (EFI_ERROR (Status)) {
828 goto ON_EXIT;
829 }
830
831 //
832 // Create a notify event to set address flag when DAD if IP6 driver succeeded.
833 //
834 Status = gBS->CreateEvent (
835 EVT_NOTIFY_SIGNAL,
836 TPL_NOTIFY,
838 &IsAddressOk,
839 &MappedEvt
840 );
841 if (EFI_ERROR (Status)) {
842 goto ON_EXIT;
843 }
844
845 //
846 // Set static host ip6 address. This is a asynchronous process.
847 //
848 Status = Ip6Cfg->RegisterDataNotify (
849 Ip6Cfg,
851 MappedEvt
852 );
853 if (EFI_ERROR (Status)) {
854 goto ON_EXIT;
855 }
856
857 Status = Ip6Cfg->SetData (
858 Ip6Cfg,
861 &CfgAddr
862 );
863 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
864 goto ON_EXIT;
865 } else if (Status == EFI_NOT_READY) {
866 //
867 // Poll the network until the asynchronous process is finished.
868 //
869 while (!IsAddressOk) {
870 Ip6->Poll (Ip6);
871 }
872
873 //
874 // Check whether the Ip6 Address setting is successed.
875 //
876 DataSize = 0;
877 Status = Ip6Cfg->GetData (
878 Ip6Cfg,
880 &DataSize,
881 NULL
882 );
883 if ((Status != EFI_BUFFER_TOO_SMALL) || (DataSize == 0)) {
884 Status = EFI_DEVICE_ERROR;
885 goto ON_EXIT;
886 }
887
888 Ip6Addr = AllocatePool (DataSize);
889 if (Ip6Addr == NULL) {
890 return EFI_OUT_OF_RESOURCES;
891 }
892
893 Status = Ip6Cfg->GetData (
894 Ip6Cfg,
896 &DataSize,
897 (VOID *)Ip6Addr
898 );
899 if (EFI_ERROR (Status)) {
900 Status = EFI_DEVICE_ERROR;
901 goto ON_EXIT;
902 }
903
904 for (Index = 0; Index < DataSize / sizeof (EFI_IPv6_ADDRESS); Index++) {
905 if (CompareMem (Ip6Addr + Index, &CfgAddr, sizeof (EFI_IPv6_ADDRESS)) == 0) {
906 break;
907 }
908 }
909
910 if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) {
911 Status = EFI_ABORTED;
912 goto ON_EXIT;
913 }
914 }
915
916ON_EXIT:
917 if (MappedEvt != NULL) {
918 Ip6Cfg->UnregisterDataNotify (
919 Ip6Cfg,
921 MappedEvt
922 );
923 gBS->CloseEvent (MappedEvt);
924 }
925
926 if (Ip6Addr != NULL) {
927 FreePool (Ip6Addr);
928 }
929
930 return Status;
931}
932
945 )
946{
947 EFI_DHCP6_PROTOCOL *Dhcp6;
950 EFI_DHCP6_RETRANSMISSION *Retransmit;
951 EFI_DHCP6_PACKET_OPTION *OptList[HTTP_BOOT_DHCP6_OPTION_MAX_NUM];
952 UINT32 OptCount;
953 UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE];
954 EFI_STATUS Status;
955 UINT32 Random;
956
957 Dhcp6 = Private->Dhcp6;
958 ASSERT (Dhcp6 != NULL);
959
960 //
961 // Build options list for the request packet.
962 //
963 OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);
964 ASSERT (OptCount > 0);
965
966 Status = PseudoRandomU32 (&Random);
967 if (EFI_ERROR (Status)) {
968 DEBUG ((DEBUG_ERROR, "%a failed to generate random number: %r\n", __func__, Status));
969 return Status;
970 }
971
972 Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
973 if (Retransmit == NULL) {
974 return EFI_OUT_OF_RESOURCES;
975 }
976
977 ZeroMem (&Mode, sizeof (EFI_DHCP6_MODE_DATA));
978 ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA));
979
980 Config.OptionCount = OptCount;
981 Config.OptionList = OptList;
983 Config.CallbackContext = Private;
984 Config.IaInfoEvent = NULL;
985 Config.RapidCommit = FALSE;
986 Config.ReconfigureAccept = FALSE;
987 Config.IaDescriptor.IaId = Random;
989 Config.SolicitRetransmission = Retransmit;
990 Retransmit->Irt = 4;
991 Retransmit->Mrc = 4;
992 Retransmit->Mrt = 32;
993 Retransmit->Mrd = 60;
994
995 //
996 // Configure the DHCPv6 instance for HTTP boot.
997 //
998 Status = Dhcp6->Configure (Dhcp6, &Config);
999 FreePool (Retransmit);
1000 if (EFI_ERROR (Status)) {
1001 goto ON_EXIT;
1002 }
1003
1004 //
1005 // Initialize the record fields for DHCPv6 offer in private data.
1006 //
1007 Private->OfferNum = 0;
1008 Private->SelectIndex = 0;
1009 ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
1010 ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));
1011
1012 //
1013 // Start DHCPv6 S.A.R.R. process to acquire IPv6 address.
1014 //
1015 Status = Dhcp6->Start (Dhcp6);
1016 if (EFI_ERROR (Status)) {
1017 goto ON_EXIT;
1018 }
1019
1020 //
1021 // Get the acquired IPv6 address and store them.
1022 //
1023 Status = Dhcp6->GetModeData (Dhcp6, &Mode, NULL);
1024 if (EFI_ERROR (Status)) {
1025 goto ON_EXIT;
1026 }
1027
1028 ASSERT (Mode.Ia->State == Dhcp6Bound);
1029 CopyMem (&Private->StationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS));
1030
1031 AsciiPrint ("\n Station IPv6 address is ");
1032 HttpBootShowIp6Addr (&Private->StationIp.v6);
1033 AsciiPrint ("\n");
1034
1035ON_EXIT:
1036 if (EFI_ERROR (Status)) {
1037 Dhcp6->Stop (Dhcp6);
1038 Dhcp6->Configure (Dhcp6, NULL);
1039 } else {
1040 ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA));
1041 Dhcp6->Configure (Dhcp6, &Config);
1042 if (Mode.ClientId != NULL) {
1043 FreePool (Mode.ClientId);
1044 }
1045
1046 if (Mode.Ia != NULL) {
1047 FreePool (Mode.Ia);
1048 }
1049 }
1050
1051 return Status;
1052}
UINT64 UINTN
UINTN EFIAPI AsciiStrLen(IN CONST CHAR8 *String)
Definition: String.c:641
INTN EFIAPI CompareMem(IN CONST VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
#define EFI_DHCP6_IA_TYPE_NA
Definition: Dhcp6.h:134
EFI_DHCP6_EVENT
Definition: Dhcp6.h:76
@ Dhcp6RcvdReply
Definition: Dhcp6.h:99
@ Dhcp6RcvdAdvertise
Definition: Dhcp6.h:85
@ Dhcp6SendRequest
Definition: Dhcp6.h:95
@ Dhcp6SendSolicit
Definition: Dhcp6.h:81
@ Dhcp6SelectAdvertise
Definition: Dhcp6.h:90
EFI_DHCP6_STATE
Definition: Dhcp6.h:28
@ Dhcp6Bound
Definition: Dhcp6.h:63
VOID *EFIAPI AllocateZeroPool(IN UINTN AllocationSize)
VOID EFIAPI FreePool(IN VOID *Buffer)
@ HttpBootDhcp6
VOID HttpBootSelectDhcpOffer(IN HTTP_BOOT_PRIVATE_DATA *Private)
HTTP_BOOT_OFFER_TYPE
Definition: HttpBootDhcp4.h:56
EFI_STATUS HttpBootSetIp6Gateway(IN HTTP_BOOT_PRIVATE_DATA *Private)
UINT32 HttpBootBuildDhcp6Options(IN HTTP_BOOT_PRIVATE_DATA *Private, OUT EFI_DHCP6_PACKET_OPTION **OptList, IN UINT8 *Buffer)
Definition: HttpBootDhcp6.c:23
EFI_STATUS HttpBootCheckRouteTable(IN HTTP_BOOT_PRIVATE_DATA *Private, IN UINTN TimeOutInSecond, OUT EFI_IPv6_ADDRESS *GatewayAddr)
EFI_STATUS HttpBootSetIp6Dns(IN HTTP_BOOT_PRIVATE_DATA *Private, IN UINTN DataLength, IN VOID *DnsServerData)
EFI_STATUS HttpBootCacheDhcp6Packet(IN EFI_DHCP6_PACKET *Dst, IN EFI_DHCP6_PACKET *Src)
EFI_STATUS HttpBootCacheDhcp6Offer(IN HTTP_BOOT_PRIVATE_DATA *Private, IN EFI_DHCP6_PACKET *RcvdOffer)
EFI_STATUS HttpBootSetIp6Policy(IN HTTP_BOOT_PRIVATE_DATA *Private)
EFI_STATUS HttpBootParseDhcp6Packet(IN HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6)
EFI_STATUS HttpBootDhcp6Sarr(IN HTTP_BOOT_PRIVATE_DATA *Private)
EFI_DHCP6_PACKET_OPTION * HttpBootParseDhcp6Options(IN UINT8 *Buffer, IN UINT32 Length, IN UINT16 OptTag)
EFI_STATUS EFIAPI HttpBootDhcp6CallBack(IN EFI_DHCP6_PROTOCOL *This, IN VOID *Context, IN EFI_DHCP6_STATE CurrentState, IN EFI_DHCP6_EVENT Dhcp6Event, IN EFI_DHCP6_PACKET *Packet, OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL)
EFI_STATUS HttpBootSetIp6Address(IN HTTP_BOOT_PRIVATE_DATA *Private)
VOID HttpBootShowIp6Addr(IN EFI_IPv6_ADDRESS *Ip)
VOID HttpBootUintnToAscDecWithFormat(IN UINTN Number, IN UINT8 *Buffer, IN INTN Length)
VOID EFIAPI HttpBootCommonNotify(IN EFI_EVENT Event, IN VOID *Context)
EFI_STATUS EFIAPI HttpUrlGetIp6(IN CHAR8 *Url, IN VOID *UrlParser, OUT EFI_IPv6_ADDRESS *Ip6Address)
Definition: DxeHttpLib.c:626
EFI_STATUS EFIAPI HttpParseUrl(IN CHAR8 *Url, IN UINT32 Length, IN BOOLEAN IsConnectMethod, OUT VOID **UrlParser)
Definition: DxeHttpLib.c:370
@ Ip6ConfigDataTypeGateway
Definition: Ip6Config.h:79
@ Ip6ConfigDataTypeManualAddress
Definition: Ip6Config.h:68
@ Ip6ConfigDataTypePolicy
Definition: Ip6Config.h:50
@ Ip6ConfigDataTypeDnsServer
Definition: Ip6Config.h:90
EFI_IP6_CONFIG_POLICY
Definition: Ip6Config.h:154
@ Ip6ConfigPolicyManual
Definition: Ip6Config.h:163
@ Ip6ConfigPolicyAutomatic
Definition: Ip6Config.h:175
#define NULL
Definition: Base.h:319
#define TRUE
Definition: Base.h:301
#define FALSE
Definition: Base.h:307
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define DEBUG(Expression)
Definition: DebugLib.h:434
BOOLEAN EFIAPI NetIp6IsNetEqual(EFI_IPv6_ADDRESS *Ip1, EFI_IPv6_ADDRESS *Ip2, UINT8 PrefixLength)
Definition: DxeNetLib.c:837
BOOLEAN EFIAPI NetIp6IsUnspecifiedAddr(IN EFI_IPv6_ADDRESS *Ip6)
Definition: DxeNetLib.c:766
EFI_STATUS EFIAPI PseudoRandomU32(OUT UINT32 *Output)
Definition: DxeNetLib.c:1011
VOID *EFIAPI AllocatePool(IN UINTN AllocationSize)
IPv6_ADDRESS EFI_IPv6_ADDRESS
Definition: UefiBaseType.h:90
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
VOID * EFI_EVENT
Definition: UefiBaseType.h:37
#define EFI_SUCCESS
Definition: UefiBaseType.h:112
EFI_BOOT_SERVICES * gBS
UINTN EFIAPI AsciiPrint(IN CONST CHAR8 *Format,...)
Definition: UefiLibPrint.c:250
@ TimerRelative
Definition: UefiSpec.h:539
BOOLEAN ReconfigureAccept
Definition: Dhcp6.h:366
EFI_DHCP6_IA_DESCRIPTOR IaDescriptor
Definition: Dhcp6.h:352
BOOLEAN RapidCommit
Definition: Dhcp6.h:372
UINT32 OptionCount
Definition: Dhcp6.h:340
EFI_DHCP6_RETRANSMISSION * SolicitRetransmission
Definition: Dhcp6.h:377
VOID * CallbackContext
Definition: Dhcp6.h:336
EFI_EVENT IaInfoEvent
Definition: Dhcp6.h:360
EFI_DHCP6_CALLBACK Dhcp6Callback
Definition: Dhcp6.h:332
EFI_DHCP6_PACKET_OPTION ** OptionList
Definition: Dhcp6.h:348
EFI_IPv6_ADDRESS IpAddress
Definition: Dhcp6.h:244
UINT16 Type
Type for an IA.
Definition: Dhcp6.h:256
UINT32 IaId
The identifier for an IA.
Definition: Dhcp6.h:257
EFI_DHCP6_IA_ADDRESS IaAddress[1]
Definition: Dhcp6.h:281
EFI_DHCP6_STATE State
Definition: Dhcp6.h:268
EFI_DHCP6_DUID * ClientId
Definition: Dhcp6.h:288
EFI_DHCP6_IA * Ia
Definition: Dhcp6.h:293
UINT32 Size
Definition: Dhcp6.h:185
UINT8 Option[1]
Definition: Dhcp6.h:199
BOOLEAN AcceptIcmpErrors
Definition: Ip6.h:157
UINT32 ReceiveTimeout
Definition: Ip6.h:208
UINT8 DefaultProtocol
Definition: Ip6.h:144
UINT8 HopLimit
Definition: Ip6.h:197
UINT32 TransmitTimeout
Definition: Ip6.h:214
EFI_IP6_NEIGHBOR_CACHE * NeighborCache
Definition: Ip6.h:366
EFI_IP6_ICMP_TYPE * IcmpTypeList
Definition: Ip6.h:386
UINT32 RouteCount
Definition: Ip6.h:352
EFI_IP6_ADDRESS_INFO * AddressList
Definition: Ip6.h:336
EFI_IP6_ROUTE_TABLE * RouteTable
Definition: Ip6.h:356
EFI_IPv6_ADDRESS * GroupTable
Definition: Ip6.h:347
EFI_IP6_ADDRESS_INFO * PrefixTable
Definition: Ip6.h:376
UINT8 PrefixLength
Definition: Ip6.h:243
EFI_IPv6_ADDRESS Gateway
Definition: Ip6.h:235
EFI_IPv6_ADDRESS Destination
Definition: Ip6.h:239