2 Functions implementation related with DHCPv6 for HTTP boot driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "HttpBootDxe.h"
18 Build the options buffer for the DHCPv6 request packet.
20 @param[in] Private The pointer to HTTP BOOT driver private data.
21 @param[out] OptList The pointer to the option pointer array.
22 @param[in] Buffer The pointer to the buffer to contain the option list.
24 @return Index The count of the built-in options.
28 HttpBootBuildDhcp6Options (
29 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
30 OUT EFI_DHCP6_PACKET_OPTION
**OptList
,
34 HTTP_BOOT_DHCP6_OPTION_ENTRY OptEnt
;
39 OptList
[0] = (EFI_DHCP6_PACKET_OPTION
*) Buffer
;
42 // Append client option request option
44 OptList
[Index
]->OpCode
= HTONS (HTTP_BOOT_DHCP6_OPT_ORO
);
45 OptList
[Index
]->OpLen
= HTONS (8);
46 OptEnt
.Oro
= (HTTP_BOOT_DHCP6_OPTION_ORO
*) OptList
[Index
]->Data
;
47 OptEnt
.Oro
->OpCode
[0] = HTONS(HTTP_BOOT_DHCP6_OPT_BOOT_FILE_URL
);
48 OptEnt
.Oro
->OpCode
[1] = HTONS(HTTP_BOOT_DHCP6_OPT_BOOT_FILE_PARAM
);
49 OptEnt
.Oro
->OpCode
[2] = HTONS(HTTP_BOOT_DHCP6_OPT_DNS_SERVERS
);
50 OptEnt
.Oro
->OpCode
[3] = HTONS(HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS
);
52 OptList
[Index
] = GET_NEXT_DHCP6_OPTION (OptList
[Index
- 1]);
55 // Append client network device interface option
57 OptList
[Index
]->OpCode
= HTONS (HTTP_BOOT_DHCP6_OPT_UNDI
);
58 OptList
[Index
]->OpLen
= HTONS ((UINT16
)3);
59 OptEnt
.Undi
= (HTTP_BOOT_DHCP6_OPTION_UNDI
*) OptList
[Index
]->Data
;
61 if (Private
->Nii
!= NULL
) {
62 OptEnt
.Undi
->Type
= Private
->Nii
->Type
;
63 OptEnt
.Undi
->MajorVer
= Private
->Nii
->MajorVer
;
64 OptEnt
.Undi
->MinorVer
= Private
->Nii
->MinorVer
;
66 OptEnt
.Undi
->Type
= DEFAULT_UNDI_TYPE
;
67 OptEnt
.Undi
->MajorVer
= DEFAULT_UNDI_MAJOR
;
68 OptEnt
.Undi
->MinorVer
= DEFAULT_UNDI_MINOR
;
72 OptList
[Index
] = GET_NEXT_DHCP6_OPTION (OptList
[Index
- 1]);
75 // Append client system architecture option
77 OptList
[Index
]->OpCode
= HTONS (HTTP_BOOT_DHCP6_OPT_ARCH
);
78 OptList
[Index
]->OpLen
= HTONS ((UINT16
) sizeof (HTTP_BOOT_DHCP6_OPTION_ARCH
));
79 OptEnt
.Arch
= (HTTP_BOOT_DHCP6_OPTION_ARCH
*) OptList
[Index
]->Data
;
80 Value
= HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE
);
81 CopyMem (&OptEnt
.Arch
->Type
, &Value
, sizeof (UINT16
));
83 OptList
[Index
] = GET_NEXT_DHCP6_OPTION (OptList
[Index
- 1]);
86 // Append vendor class identify option.
88 OptList
[Index
]->OpCode
= HTONS (HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS
);
89 OptList
[Index
]->OpLen
= HTONS ((UINT16
) sizeof (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS
));
90 OptEnt
.VendorClass
= (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS
*) OptList
[Index
]->Data
;
91 OptEnt
.VendorClass
->Vendor
= HTONL (HTTP_BOOT_DHCP6_ENTERPRISE_NUM
);
92 OptEnt
.VendorClass
->ClassLen
= HTONS ((UINT16
) sizeof (HTTP_BOOT_CLASS_ID
));
94 &OptEnt
.VendorClass
->ClassId
,
95 DEFAULT_CLASS_ID_DATA
,
96 sizeof (HTTP_BOOT_CLASS_ID
)
98 HttpBootUintnToAscDecWithFormat (
99 EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE
,
100 OptEnt
.VendorClass
->ClassId
.ArchitectureType
,
101 sizeof (OptEnt
.VendorClass
->ClassId
.ArchitectureType
)
104 if (Private
->Nii
!= NULL
) {
106 OptEnt
.VendorClass
->ClassId
.InterfaceName
,
107 Private
->Nii
->StringId
,
108 sizeof (OptEnt
.VendorClass
->ClassId
.InterfaceName
)
110 HttpBootUintnToAscDecWithFormat (
111 Private
->Nii
->MajorVer
,
112 OptEnt
.VendorClass
->ClassId
.UndiMajor
,
113 sizeof (OptEnt
.VendorClass
->ClassId
.UndiMajor
)
115 HttpBootUintnToAscDecWithFormat (
116 Private
->Nii
->MinorVer
,
117 OptEnt
.VendorClass
->ClassId
.UndiMinor
,
118 sizeof (OptEnt
.VendorClass
->ClassId
.UndiMinor
)
128 Parse out a DHCPv6 option by OptTag, and find the position in buffer.
130 @param[in] Buffer The pointer to the option buffer.
131 @param[in] Length Length of the option buffer.
132 @param[in] OptTag The required option tag.
134 @retval NULL Failed to parse the required option.
135 @retval Others The postion of the required option in buffer.
138 EFI_DHCP6_PACKET_OPTION
*
139 HttpBootParseDhcp6Options (
145 EFI_DHCP6_PACKET_OPTION
*Option
;
148 Option
= (EFI_DHCP6_PACKET_OPTION
*) Buffer
;
152 // OpLen and OpCode here are both stored in network order.
154 while (Offset
< Length
) {
156 if (NTOHS (Option
->OpCode
) == OptTag
) {
161 Offset
+= (NTOHS(Option
->OpLen
) + 4);
162 Option
= (EFI_DHCP6_PACKET_OPTION
*) (Buffer
+ Offset
);
170 Parse the cached DHCPv6 packet, including all the options.
172 @param[in] Cache6 The pointer to a cached DHCPv6 packet.
174 @retval EFI_SUCCESS Parsed the DHCPv6 packet successfully.
175 @retval EFI_DEVICE_ERROR Failed to parse and invalid the packet.
179 HttpBootParseDhcp6Packet (
180 IN HTTP_BOOT_DHCP6_PACKET_CACHE
*Cache6
183 EFI_DHCP6_PACKET
*Offer
;
184 EFI_DHCP6_PACKET_OPTION
**Options
;
185 EFI_DHCP6_PACKET_OPTION
*Option
;
186 HTTP_BOOT_OFFER_TYPE OfferType
;
187 EFI_IPv6_ADDRESS IpAddr
;
188 BOOLEAN IsProxyOffer
;
191 BOOLEAN IpExpressedUri
;
197 IpExpressedUri
= FALSE
;
200 Offer
= &Cache6
->Packet
.Offer
;
201 Options
= Cache6
->OptList
;
203 ZeroMem (Cache6
->OptList
, sizeof (Cache6
->OptList
));
205 Option
= (EFI_DHCP6_PACKET_OPTION
*) (Offer
->Dhcp6
.Option
);
207 Length
= GET_DHCP6_OPTION_SIZE (Offer
);
210 // OpLen and OpCode here are both stored in network order, since they are from original packet.
212 while (Offset
< Length
) {
214 if (NTOHS (Option
->OpCode
) == HTTP_BOOT_DHCP6_OPT_IA_NA
) {
215 Options
[HTTP_BOOT_DHCP6_IDX_IA_NA
] = Option
;
216 } else if (NTOHS (Option
->OpCode
) == HTTP_BOOT_DHCP6_OPT_BOOT_FILE_URL
) {
218 // The server sends this option to inform the client about an URL to a boot file.
220 Options
[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL
] = Option
;
221 } else if (NTOHS (Option
->OpCode
) == HTTP_BOOT_DHCP6_OPT_BOOT_FILE_PARAM
) {
222 Options
[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_PARAM
] = Option
;
223 } else if (NTOHS (Option
->OpCode
) == HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS
) {
224 Options
[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS
] = Option
;
225 } else if (NTOHS (Option
->OpCode
) == HTTP_BOOT_DHCP6_OPT_DNS_SERVERS
) {
226 Options
[HTTP_BOOT_DHCP6_IDX_DNS_SERVER
] = Option
;
229 Offset
+= (NTOHS (Option
->OpLen
) + 4);
230 Option
= (EFI_DHCP6_PACKET_OPTION
*) (Offer
->Dhcp6
.Option
+ Offset
);
233 // The offer with assigned client address is NOT a proxy offer.
234 // An ia_na option, embeded with valid ia_addr option and a status_code of success.
236 Option
= Options
[HTTP_BOOT_DHCP6_IDX_IA_NA
];
237 if (Option
!= NULL
) {
238 Option
= HttpBootParseDhcp6Options (
240 NTOHS (Option
->OpLen
),
241 HTTP_BOOT_DHCP6_OPT_STATUS_CODE
243 if ((Option
!= NULL
&& Option
->Data
[0] == 0) || (Option
== NULL
)) {
244 IsProxyOffer
= FALSE
;
249 // The offer with "HTTPClient" is a Http offer.
251 Option
= Options
[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS
];
253 if (Option
!= NULL
&&
254 NTOHS(Option
->OpLen
) >= 10 &&
255 CompareMem (Option
->Data
, DEFAULT_CLASS_ID_DATA
, 10) == 0) {
260 // The offer with Domain Server is a DNS offer.
262 Option
= Options
[HTTP_BOOT_DHCP6_IDX_DNS_SERVER
];
263 if (Option
!= NULL
) {
268 // Http offer must have a boot URI.
270 if (IsHttpOffer
&& Options
[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL
] == NULL
) {
271 return EFI_DEVICE_ERROR
;
275 // Try to retrieve the IP of HTTP server from URI.
278 Status
= HttpParseUrl (
279 (CHAR8
*) Options
[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL
]->Data
,
280 (UINT32
) AsciiStrLen ((CHAR8
*) Options
[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL
]->Data
),
284 if (EFI_ERROR (Status
)) {
285 return EFI_DEVICE_ERROR
;
288 Status
= HttpUrlGetIp6 (
289 (CHAR8
*) Options
[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL
]->Data
,
293 IpExpressedUri
= !EFI_ERROR (Status
);
297 // Determine offer type of the DHCPv6 packet.
300 if (IpExpressedUri
) {
301 OfferType
= IsProxyOffer
? HttpOfferTypeProxyIpUri
: HttpOfferTypeDhcpIpUri
;
304 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpNameUriDns
: HttpOfferTypeDhcpNameUri
;
306 OfferType
= HttpOfferTypeProxyNameUri
;
312 OfferType
= IsDnsOffer
? HttpOfferTypeDhcpDns
: HttpOfferTypeDhcpOnly
;
314 return EFI_DEVICE_ERROR
;
318 Cache6
->OfferType
= OfferType
;
323 Cache the DHCPv6 packet.
325 @param[in] Dst The pointer to the cache buffer for DHCPv6 packet.
326 @param[in] Src The pointer to the DHCPv6 packet to be cached.
330 HttpBootCacheDhcp6Packet (
331 IN EFI_DHCP6_PACKET
*Dst
,
332 IN EFI_DHCP6_PACKET
*Src
335 ASSERT (Dst
->Size
>= Src
->Length
);
337 CopyMem (&Dst
->Dhcp6
, &Src
->Dhcp6
, Src
->Length
);
338 Dst
->Length
= Src
->Length
;
342 Cache all the received DHCPv6 offers, and set OfferIndex and OfferCount.
344 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
345 @param[in] RcvdOffer The pointer to the received offer packet.
349 HttpBootCacheDhcp6Offer (
350 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
351 IN EFI_DHCP6_PACKET
*RcvdOffer
354 HTTP_BOOT_DHCP6_PACKET_CACHE
*Cache6
;
355 EFI_DHCP6_PACKET
*Offer
;
356 HTTP_BOOT_OFFER_TYPE OfferType
;
358 Cache6
= &Private
->OfferBuffer
[Private
->OfferNum
].Dhcp6
;
359 Offer
= &Cache6
->Packet
.Offer
;
362 // Cache the content of DHCPv6 packet firstly.
364 HttpBootCacheDhcp6Packet(Offer
, RcvdOffer
);
367 // Validate the DHCPv6 packet, and parse the options and offer type.
369 if (EFI_ERROR (HttpBootParseDhcp6Packet (Cache6
))) {
374 // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.
376 OfferType
= Cache6
->OfferType
;
377 ASSERT (OfferType
< HttpOfferTypeMax
);
378 ASSERT (Private
->OfferCount
[OfferType
] < HTTP_BOOT_OFFER_MAX_NUM
);
379 Private
->OfferIndex
[OfferType
][Private
->OfferCount
[OfferType
]] = Private
->OfferNum
;
380 Private
->OfferCount
[OfferType
]++;
385 EFI_DHCP6_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol driver
386 to intercept events that occurred in the configuration process.
388 @param[in] This The pointer to the EFI DHCPv6 Protocol.
389 @param[in] Context The pointer to the context set by EFI_DHCP6_PROTOCOL.Configure().
390 @param[in] CurrentState The current operational state of the EFI DHCPv Protocol driver.
391 @param[in] Dhcp6Event The event that occurs in the current state, which usually means a
393 @param[in] Packet The DHCPv6 packet that is going to be sent or was already received.
394 @param[out] NewPacket The packet that is used to replace the Packet above.
396 @retval EFI_SUCCESS Told the EFI DHCPv6 Protocol driver to continue the DHCP process.
397 @retval EFI_NOT_READY Only used in the Dhcp6Selecting state. The EFI DHCPv6 Protocol
398 driver will continue to wait for more packets.
399 @retval EFI_ABORTED Told the EFI DHCPv6 Protocol driver to abort the current process.
404 HttpBootDhcp6CallBack (
405 IN EFI_DHCP6_PROTOCOL
*This
,
407 IN EFI_DHCP6_STATE CurrentState
,
408 IN EFI_DHCP6_EVENT Dhcp6Event
,
409 IN EFI_DHCP6_PACKET
*Packet
,
410 OUT EFI_DHCP6_PACKET
**NewPacket OPTIONAL
413 HTTP_BOOT_PRIVATE_DATA
*Private
;
414 EFI_DHCP6_PACKET
*SelectAd
;
416 if ((Dhcp6Event
!= Dhcp6RcvdAdvertise
) && (Dhcp6Event
!= Dhcp6SelectAdvertise
)) {
420 ASSERT (Packet
!= NULL
);
422 Private
= (HTTP_BOOT_PRIVATE_DATA
*) Context
;
423 Status
= EFI_SUCCESS
;
424 switch (Dhcp6Event
) {
426 case Dhcp6RcvdAdvertise
:
427 Status
= EFI_NOT_READY
;
428 if (Private
->OfferNum
< HTTP_BOOT_OFFER_MAX_NUM
) {
430 // Cache the dhcp offers to OfferBuffer[] for select later, and record
431 // the OfferIndex and OfferCount.
433 HttpBootCacheDhcp6Offer (Private
, Packet
);
437 case Dhcp6SelectAdvertise
:
439 // Select offer by the default policy or by order, and record the SelectIndex
440 // and SelectProxyType.
442 HttpBootSelectDhcpOffer (Private
);
444 if (Private
->SelectIndex
== 0) {
445 Status
= EFI_ABORTED
;
447 ASSERT (NewPacket
!= NULL
);
448 SelectAd
= &Private
->OfferBuffer
[Private
->SelectIndex
- 1].Dhcp6
.Packet
.Offer
;
449 *NewPacket
= AllocateZeroPool (SelectAd
->Size
);
450 ASSERT (*NewPacket
!= NULL
);
451 CopyMem (*NewPacket
, SelectAd
, SelectAd
->Size
);
463 Check whether IP driver could route the message which will be sent to ServerIp address.
465 This function will check the IP6 route table every 1 seconds until specified timeout is expired, if a valid
466 route is found in IP6 route table, the address will be filed in GatewayAddr and return.
468 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
469 @param[in] TimeOutInSecond Timeout value in seconds.
470 @param[out] GatewayAddr Pointer to store the gateway IP address.
472 @retval EFI_SUCCESS Found a valid gateway address successfully.
473 @retval EFI_TIMEOUT The operation is time out.
474 @retval Other Unexpect error happened.
478 HttpBootCheckRouteTable (
479 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
480 IN UINTN TimeOutInSecond
,
481 OUT EFI_IPv6_ADDRESS
*GatewayAddr
485 EFI_IP6_PROTOCOL
*Ip6
;
486 EFI_IP6_MODE_DATA Ip6ModeData
;
488 EFI_EVENT TimeOutEvt
;
490 BOOLEAN GatewayIsFound
;
492 ASSERT (GatewayAddr
!= NULL
);
493 ASSERT (Private
!= NULL
);
496 GatewayIsFound
= FALSE
;
499 Status
= EFI_SUCCESS
;
500 ZeroMem (GatewayAddr
, sizeof (EFI_IPv6_ADDRESS
));
503 Status
= Ip6
->GetModeData (Ip6
, &Ip6ModeData
, NULL
, NULL
);
504 if (EFI_ERROR (Status
)) {
509 // Find out the gateway address which can route the message which send to ServerIp.
511 for (Index
= 0; Index
< Ip6ModeData
.RouteCount
; Index
++) {
512 if (NetIp6IsNetEqual (&Private
->ServerIp
.v6
, &Ip6ModeData
.RouteTable
[Index
].Destination
, Ip6ModeData
.RouteTable
[Index
].PrefixLength
)) {
513 IP6_COPY_ADDRESS (GatewayAddr
, &Ip6ModeData
.RouteTable
[Index
].Gateway
);
514 GatewayIsFound
= TRUE
;
519 if (Ip6ModeData
.AddressList
!= NULL
) {
520 FreePool (Ip6ModeData
.AddressList
);
522 if (Ip6ModeData
.GroupTable
!= NULL
) {
523 FreePool (Ip6ModeData
.GroupTable
);
525 if (Ip6ModeData
.RouteTable
!= NULL
) {
526 FreePool (Ip6ModeData
.RouteTable
);
528 if (Ip6ModeData
.NeighborCache
!= NULL
) {
529 FreePool (Ip6ModeData
.NeighborCache
);
531 if (Ip6ModeData
.PrefixTable
!= NULL
) {
532 FreePool (Ip6ModeData
.PrefixTable
);
534 if (Ip6ModeData
.IcmpTypeList
!= NULL
) {
535 FreePool (Ip6ModeData
.IcmpTypeList
);
538 if (GatewayIsFound
|| RetryCount
== TimeOutInSecond
) {
545 // Delay 1 second then recheck it again.
547 if (TimeOutEvt
== NULL
) {
548 Status
= gBS
->CreateEvent (
555 if (EFI_ERROR (Status
)) {
560 Status
= gBS
->SetTimer (TimeOutEvt
, TimerRelative
, TICKS_PER_SECOND
);
561 if (EFI_ERROR (Status
)) {
564 while (EFI_ERROR (gBS
->CheckEvent (TimeOutEvt
))) {
570 if (TimeOutEvt
!= NULL
) {
571 gBS
->CloseEvent (TimeOutEvt
);
574 if (GatewayIsFound
) {
575 Status
= EFI_SUCCESS
;
576 } else if (RetryCount
== TimeOutInSecond
) {
577 Status
= EFI_TIMEOUT
;
584 Set the IP6 policy to Automatic.
586 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
588 @retval EFI_SUCCESS Switch the IP policy succesfully.
589 @retval Others Unexpect error happened.
593 HttpBootSetIp6Policy (
594 IN HTTP_BOOT_PRIVATE_DATA
*Private
597 EFI_IP6_CONFIG_POLICY Policy
;
598 EFI_IP6_CONFIG_PROTOCOL
*Ip6Config
;
602 Ip6Config
= Private
->Ip6Config
;
603 DataSize
= sizeof (EFI_IP6_CONFIG_POLICY
);
606 // Get and store the current policy of IP6 driver.
608 Status
= Ip6Config
->GetData (
610 Ip6ConfigDataTypePolicy
,
614 if (EFI_ERROR (Status
)) {
618 if (Policy
== Ip6ConfigPolicyManual
) {
619 Policy
= Ip6ConfigPolicyAutomatic
;
620 Status
= Ip6Config
->SetData (
622 Ip6ConfigDataTypePolicy
,
623 sizeof(EFI_IP6_CONFIG_POLICY
),
626 if (EFI_ERROR (Status
)) {
634 This function will register the default DNS addresses to the network device.
636 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
637 @param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes.
638 @param[in] DnsServerData Point a list of DNS server address in an array
639 of EFI_IPv6_ADDRESS instances.
641 @retval EFI_SUCCESS The DNS configuration has been configured successfully.
642 @retval Others Failed to configure the address.
647 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
649 IN VOID
*DnsServerData
652 EFI_IP6_CONFIG_PROTOCOL
*Ip6Config
;
654 ASSERT (Private
->UsingIpv6
);
656 Ip6Config
= Private
->Ip6Config
;
658 return Ip6Config
->SetData (
660 Ip6ConfigDataTypeDnsServer
,
667 This function will register the IPv6 gateway address to the network device.
669 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
671 @retval EFI_SUCCESS The new IP configuration has been configured successfully.
672 @retval Others Failed to configure the address.
676 HttpBootSetIp6Gateway (
677 IN HTTP_BOOT_PRIVATE_DATA
*Private
680 EFI_IP6_CONFIG_PROTOCOL
*Ip6Config
;
683 ASSERT (Private
->UsingIpv6
);
684 Ip6Config
= Private
->Ip6Config
;
687 // Set the default gateway address.
689 if (!Private
->NoGateway
&& !NetIp6IsUnspecifiedAddr (&Private
->GatewayIp
.v6
)) {
690 Status
= Ip6Config
->SetData (
692 Ip6ConfigDataTypeGateway
,
693 sizeof (EFI_IPv6_ADDRESS
),
694 &Private
->GatewayIp
.v6
696 if (EFI_ERROR(Status
)) {
705 This function will register the station IP address.
707 @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.
709 @retval EFI_SUCCESS The new IP address has been configured successfully.
710 @retval Others Failed to configure the address.
714 HttpBootSetIp6Address (
715 IN HTTP_BOOT_PRIVATE_DATA
*Private
719 EFI_IP6_PROTOCOL
*Ip6
;
720 EFI_IP6_CONFIG_PROTOCOL
*Ip6Cfg
;
721 EFI_IP6_CONFIG_POLICY Policy
;
722 EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr
;
723 EFI_IPv6_ADDRESS
*Ip6Addr
;
724 EFI_IPv6_ADDRESS GatewayAddr
;
725 EFI_IP6_CONFIG_DATA Ip6CfgData
;
731 ASSERT (Private
->UsingIpv6
);
736 Ip6Cfg
= Private
->Ip6Config
;
739 ZeroMem (&CfgAddr
, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
740 CopyMem (&CfgAddr
, &Private
->StationIp
.v6
, sizeof (EFI_IPv6_ADDRESS
));
741 ZeroMem (&Ip6CfgData
, sizeof (EFI_IP6_CONFIG_DATA
));
743 Ip6CfgData
.AcceptIcmpErrors
= TRUE
;
744 Ip6CfgData
.DefaultProtocol
= IP6_ICMP
;
745 Ip6CfgData
.HopLimit
= HTTP_BOOT_DEFAULT_HOPLIMIT
;
746 Ip6CfgData
.ReceiveTimeout
= HTTP_BOOT_DEFAULT_LIFETIME
;
747 Ip6CfgData
.TransmitTimeout
= HTTP_BOOT_DEFAULT_LIFETIME
;
749 Status
= Ip6
->Configure (Ip6
, &Ip6CfgData
);
750 if (EFI_ERROR (Status
)) {
755 // Retrieve the gateway address from IP6 route table.
757 Status
= HttpBootCheckRouteTable (Private
, HTTP_BOOT_IP6_ROUTE_TABLE_TIMEOUT
, &GatewayAddr
);
758 if (EFI_ERROR (Status
)) {
759 Private
->NoGateway
= TRUE
;
761 IP6_COPY_ADDRESS (&Private
->GatewayIp
.v6
, &GatewayAddr
);
765 // Set the new address by Ip6ConfigProtocol manually.
767 Policy
= Ip6ConfigPolicyManual
;
768 Status
= Ip6Cfg
->SetData (
770 Ip6ConfigDataTypePolicy
,
771 sizeof(EFI_IP6_CONFIG_POLICY
),
774 if (EFI_ERROR (Status
)) {
779 // Create a notify event to set address flag when DAD if IP6 driver succeeded.
781 Status
= gBS
->CreateEvent (
784 HttpBootCommonNotify
,
788 if (EFI_ERROR (Status
)) {
793 // Set static host ip6 address. This is a asynchronous process.
795 Status
= Ip6Cfg
->RegisterDataNotify (
797 Ip6ConfigDataTypeManualAddress
,
800 if (EFI_ERROR(Status
)) {
804 Status
= Ip6Cfg
->SetData (
806 Ip6ConfigDataTypeManualAddress
,
807 sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
),
810 if (EFI_ERROR (Status
) && Status
!= EFI_NOT_READY
) {
812 } else if (Status
== EFI_NOT_READY
) {
814 // Poll the network until the asynchronous process is finished.
816 while (!IsAddressOk
) {
820 // Check whether the Ip6 Address setting is successed.
823 Status
= Ip6Cfg
->GetData (
825 Ip6ConfigDataTypeManualAddress
,
829 if (Status
!= EFI_BUFFER_TOO_SMALL
|| DataSize
== 0) {
830 Status
= EFI_DEVICE_ERROR
;
834 Ip6Addr
= AllocatePool (DataSize
);
835 if (Ip6Addr
== NULL
) {
836 return EFI_OUT_OF_RESOURCES
;
838 Status
= Ip6Cfg
->GetData (
840 Ip6ConfigDataTypeManualAddress
,
844 if (EFI_ERROR (Status
)) {
845 Status
= EFI_DEVICE_ERROR
;
849 for (Index
= 0; Index
< DataSize
/ sizeof (EFI_IPv6_ADDRESS
); Index
++) {
850 if (CompareMem (Ip6Addr
+ Index
, &CfgAddr
, sizeof (EFI_IPv6_ADDRESS
)) == 0) {
854 if (Index
== DataSize
/ sizeof (EFI_IPv6_ADDRESS
)) {
855 Status
= EFI_ABORTED
;
861 if (MappedEvt
!= NULL
) {
862 Ip6Cfg
->UnregisterDataNotify (
864 Ip6ConfigDataTypeManualAddress
,
867 gBS
->CloseEvent (MappedEvt
);
870 if (Ip6Addr
!= NULL
) {
878 Start the S.A.R.R DHCPv6 process to acquire the IPv6 address and other Http boot information.
880 @param[in] Private Pointer to HTTP_BOOT private data.
882 @retval EFI_SUCCESS The S.A.R.R process successfully finished.
883 @retval Others Failed to finish the S.A.R.R process.
888 IN HTTP_BOOT_PRIVATE_DATA
*Private
891 EFI_DHCP6_PROTOCOL
*Dhcp6
;
892 EFI_DHCP6_CONFIG_DATA Config
;
893 EFI_DHCP6_MODE_DATA Mode
;
894 EFI_DHCP6_RETRANSMISSION
*Retransmit
;
895 EFI_DHCP6_PACKET_OPTION
*OptList
[HTTP_BOOT_DHCP6_OPTION_MAX_NUM
];
897 UINT8 Buffer
[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE
];
900 Dhcp6
= Private
->Dhcp6
;
901 ASSERT (Dhcp6
!= NULL
);
904 // Build options list for the request packet.
906 OptCount
= HttpBootBuildDhcp6Options (Private
, OptList
, Buffer
);
907 ASSERT (OptCount
>0);
909 Retransmit
= AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION
));
910 if (Retransmit
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
914 ZeroMem (&Mode
, sizeof (EFI_DHCP6_MODE_DATA
));
915 ZeroMem (&Config
, sizeof (EFI_DHCP6_CONFIG_DATA
));
917 Config
.OptionCount
= OptCount
;
918 Config
.OptionList
= OptList
;
919 Config
.Dhcp6Callback
= HttpBootDhcp6CallBack
;
920 Config
.CallbackContext
= Private
;
921 Config
.IaInfoEvent
= NULL
;
922 Config
.RapidCommit
= FALSE
;
923 Config
.ReconfigureAccept
= FALSE
;
924 Config
.IaDescriptor
.IaId
= NET_RANDOM (NetRandomInitSeed ());
925 Config
.IaDescriptor
.Type
= EFI_DHCP6_IA_TYPE_NA
;
926 Config
.SolicitRetransmission
= Retransmit
;
929 Retransmit
->Mrt
= 32;
930 Retransmit
->Mrd
= 60;
933 // Configure the DHCPv6 instance for HTTP boot.
935 Status
= Dhcp6
->Configure (Dhcp6
, &Config
);
936 FreePool (Retransmit
);
937 if (EFI_ERROR (Status
)) {
941 // Initialize the record fields for DHCPv6 offer in private data.
943 Private
->OfferNum
= 0;
944 Private
->SelectIndex
= 0;
945 ZeroMem (Private
->OfferCount
, sizeof (Private
->OfferCount
));
946 ZeroMem (Private
->OfferIndex
, sizeof (Private
->OfferIndex
));
949 // Start DHCPv6 S.A.R.R. process to acquire IPv6 address.
951 Status
= Dhcp6
->Start (Dhcp6
);
952 if (EFI_ERROR (Status
)) {
957 // Get the acquired IPv6 address and store them.
959 Status
= Dhcp6
->GetModeData (Dhcp6
, &Mode
, NULL
);
960 if (EFI_ERROR (Status
)) {
964 ASSERT (Mode
.Ia
->State
== Dhcp6Bound
);
965 CopyMem (&Private
->StationIp
.v6
, &Mode
.Ia
->IaAddress
[0].IpAddress
, sizeof (EFI_IPv6_ADDRESS
));
967 AsciiPrint ("\n Station IPv6 address is ");
968 HttpBootShowIp6Addr (&Private
->StationIp
.v6
);
972 if (EFI_ERROR (Status
)) {
974 Dhcp6
->Configure (Dhcp6
, NULL
);
976 ZeroMem (&Config
, sizeof (EFI_DHCP6_CONFIG_DATA
));
977 ZeroMem (&Mode
, sizeof (EFI_DHCP6_MODE_DATA
));
978 Dhcp6
->Configure (Dhcp6
, &Config
);