/** @file\r
Functions implementation related with DHCPv6 for HTTP boot driver.\r
\r
-Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
-This program and the accompanying materials are licensed and made available under \r
-the terms and conditions of the BSD License that accompanies this distribution. \r
-The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php. \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
EFI_STATUS Status;\r
UINT32 Offset;\r
UINT32 Length;\r
- \r
+\r
IsDnsOffer = FALSE;\r
IpExpressedUri = FALSE;\r
IsProxyOffer = TRUE;\r
IsHttpOffer = FALSE;\r
Offer = &Cache6->Packet.Offer;\r
Options = Cache6->OptList;\r
- \r
+\r
ZeroMem (Cache6->OptList, sizeof (Cache6->OptList));\r
\r
Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option);\r
if (IsHttpOffer && Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] == NULL) {\r
return EFI_DEVICE_ERROR;\r
}\r
- \r
+\r
//\r
- // Try to retrieve the IP of HTTP server from URI. \r
+ // Try to retrieve the IP of HTTP server from URI.\r
//\r
if (IsHttpOffer) {\r
Status = HttpParseUrl (\r
return EFI_DEVICE_ERROR;\r
}\r
}\r
- \r
+\r
Cache6->OfferType = OfferType;\r
return EFI_SUCCESS;\r
}\r
@param[in] Dst The pointer to the cache buffer for DHCPv6 packet.\r
@param[in] Src The pointer to the DHCPv6 packet to be cached.\r
\r
+ @retval EFI_SUCCESS Packet is copied.\r
+ @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet.\r
+\r
**/\r
-VOID\r
+EFI_STATUS\r
HttpBootCacheDhcp6Packet (\r
IN EFI_DHCP6_PACKET *Dst,\r
IN EFI_DHCP6_PACKET *Src\r
)\r
{\r
- ASSERT (Dst->Size >= Src->Length);\r
+ if (Dst->Size < Src->Length) {\r
+ return EFI_BUFFER_TOO_SMALL;\r
+ }\r
\r
CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length);\r
Dst->Length = Src->Length;\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
@param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.\r
@param[in] RcvdOffer The pointer to the received offer packet.\r
\r
+ @retval EFI_SUCCESS Cache and parse the packet successfully.\r
+ @retval Others Operation failed.\r
+\r
**/\r
-VOID\r
+EFI_STATUS\r
HttpBootCacheDhcp6Offer (\r
IN HTTP_BOOT_PRIVATE_DATA *Private,\r
IN EFI_DHCP6_PACKET *RcvdOffer\r
HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6;\r
EFI_DHCP6_PACKET *Offer;\r
HTTP_BOOT_OFFER_TYPE OfferType;\r
+ EFI_STATUS Status;\r
\r
Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6;\r
Offer = &Cache6->Packet.Offer;\r
//\r
// Cache the content of DHCPv6 packet firstly.\r
//\r
- HttpBootCacheDhcp6Packet(Offer, RcvdOffer);\r
+ Status = HttpBootCacheDhcp6Packet(Offer, RcvdOffer);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
//\r
// Validate the DHCPv6 packet, and parse the options and offer type.\r
//\r
if (EFI_ERROR (HttpBootParseDhcp6Packet (Cache6))) {\r
- return ;\r
+ return EFI_ABORTED;\r
}\r
\r
//\r
ASSERT (Private->OfferCount[OfferType] < HTTP_BOOT_OFFER_MAX_NUM);\r
Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;\r
Private->OfferCount[OfferType]++;\r
- Private->OfferNum++; \r
+ Private->OfferNum++;\r
+\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL\r
)\r
{\r
- HTTP_BOOT_PRIVATE_DATA *Private;\r
- EFI_DHCP6_PACKET *SelectAd;\r
- EFI_STATUS Status;\r
- if ((Dhcp6Event != Dhcp6RcvdAdvertise) && (Dhcp6Event != Dhcp6SelectAdvertise)) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- ASSERT (Packet != NULL);\r
- \r
- Private = (HTTP_BOOT_PRIVATE_DATA *) Context;\r
- Status = EFI_SUCCESS;\r
- switch (Dhcp6Event) {\r
- \r
- case Dhcp6RcvdAdvertise:\r
- Status = EFI_NOT_READY;\r
- if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) {\r
- //\r
- // Cache the dhcp offers to OfferBuffer[] for select later, and record\r
- // the OfferIndex and OfferCount.\r
- //\r
- HttpBootCacheDhcp6Offer (Private, Packet);\r
- }\r
- break;\r
-\r
- case Dhcp6SelectAdvertise:\r
- //\r
- // Select offer by the default policy or by order, and record the SelectIndex\r
- // and SelectProxyType.\r
- //\r
- HttpBootSelectDhcpOffer (Private);\r
-\r
- if (Private->SelectIndex == 0) {\r
- Status = EFI_ABORTED;\r
- } else {\r
- ASSERT (NewPacket != NULL);\r
- SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;\r
- *NewPacket = AllocateZeroPool (SelectAd->Size);\r
- if (*NewPacket == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- CopyMem (*NewPacket, SelectAd, SelectAd->Size);\r
- }\r
- break;\r
- \r
- default:\r
- break;\r
- }\r
-\r
- return Status; \r
+ HTTP_BOOT_PRIVATE_DATA *Private;\r
+ EFI_DHCP6_PACKET *SelectAd;\r
+ EFI_STATUS Status;\r
+ BOOLEAN Received;\r
+\r
+ if ((Dhcp6Event != Dhcp6SendSolicit) &&\r
+ (Dhcp6Event != Dhcp6RcvdAdvertise) &&\r
+ (Dhcp6Event != Dhcp6SendRequest) &&\r
+ (Dhcp6Event != Dhcp6RcvdReply) &&\r
+ (Dhcp6Event != Dhcp6SelectAdvertise)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ ASSERT (Packet != NULL);\r
+\r
+ Private = (HTTP_BOOT_PRIVATE_DATA *) Context;\r
+ Status = EFI_SUCCESS;\r
+ if (Private->HttpBootCallback != NULL && Dhcp6Event != Dhcp6SelectAdvertise) {\r
+ Received = (BOOLEAN) (Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply);\r
+ Status = Private->HttpBootCallback->Callback (\r
+ Private->HttpBootCallback,\r
+ HttpBootDhcp6,\r
+ Received,\r
+ Packet->Length,\r
+ &Packet->Dhcp6\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_ABORTED;\r
+ }\r
+ }\r
+ switch (Dhcp6Event) {\r
+\r
+ case Dhcp6RcvdAdvertise:\r
+ Status = EFI_NOT_READY;\r
+ if (Packet->Length > HTTP_BOOT_DHCP6_PACKET_MAX_SIZE) {\r
+ //\r
+ // Ignore the incoming packets which exceed the maximum length.\r
+ //\r
+ break;\r
+ }\r
+ if (Private->OfferNum < HTTP_BOOT_OFFER_MAX_NUM) {\r
+ //\r
+ // Cache the dhcp offers to OfferBuffer[] for select later, and record\r
+ // the OfferIndex and OfferCount.\r
+ // If error happens, just ignore this packet and continue to wait more offer.\r
+ //\r
+ HttpBootCacheDhcp6Offer (Private, Packet);\r
+ }\r
+ break;\r
+\r
+ case Dhcp6SelectAdvertise:\r
+ //\r
+ // Select offer by the default policy or by order, and record the SelectIndex\r
+ // and SelectProxyType.\r
+ //\r
+ HttpBootSelectDhcpOffer (Private);\r
+\r
+ if (Private->SelectIndex == 0) {\r
+ Status = EFI_ABORTED;\r
+ } else {\r
+ ASSERT (NewPacket != NULL);\r
+ SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;\r
+ *NewPacket = AllocateZeroPool (SelectAd->Size);\r
+ if (*NewPacket == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ CopyMem (*NewPacket, SelectAd, SelectAd->Size);\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+\r
+ return Status;\r
}\r
\r
/**\r
Check whether IP driver could route the message which will be sent to ServerIp address.\r
- \r
+\r
This function will check the IP6 route table every 1 seconds until specified timeout is expired, if a valid\r
route is found in IP6 route table, the address will be filed in GatewayAddr and return.\r
\r
@retval EFI_SUCCESS Found a valid gateway address successfully.\r
@retval EFI_TIMEOUT The operation is time out.\r
@retval Other Unexpect error happened.\r
- \r
+\r
**/\r
EFI_STATUS\r
HttpBootCheckRouteTable (\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
- \r
+\r
//\r
// Find out the gateway address which can route the message which send to ServerIp.\r
//\r
if (Ip6ModeData.IcmpTypeList != NULL) {\r
FreePool (Ip6ModeData.IcmpTypeList);\r
}\r
- \r
+\r
if (GatewayIsFound || RetryCount == TimeOutInSecond) {\r
break;\r
}\r
- \r
+\r
RetryCount++;\r
- \r
+\r
//\r
// Delay 1 second then recheck it again.\r
//\r
Ip6->Poll (Ip6);\r
}\r
}\r
- \r
+\r
ON_EXIT:\r
if (TimeOutEvt != NULL) {\r
gBS->CloseEvent (TimeOutEvt);\r
}\r
- \r
+\r
if (GatewayIsFound) {\r
Status = EFI_SUCCESS;\r
} else if (RetryCount == TimeOutInSecond) {\r
Status = EFI_TIMEOUT;\r
}\r
\r
- return Status; \r
+ return Status;\r
}\r
\r
/**\r
\r
Ip6Config = Private->Ip6Config;\r
DataSize = sizeof (EFI_IP6_CONFIG_POLICY);\r
- \r
+\r
//\r
// Get and store the current policy of IP6 driver.\r
//\r
\r
/**\r
This function will register the default DNS addresses to the network device.\r
- \r
+\r
@param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.\r
@param[in] DataLength Size of the buffer pointed to by DnsServerData in bytes.\r
@param[in] DnsServerData Point a list of DNS server address in an array\r
)\r
{\r
EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
- \r
+\r
ASSERT (Private->UsingIpv6);\r
\r
Ip6Config = Private->Ip6Config;\r
- \r
+\r
return Ip6Config->SetData (\r
Ip6Config,\r
Ip6ConfigDataTypeDnsServer,\r
\r
/**\r
This function will register the IPv6 gateway address to the network device.\r
- \r
+\r
@param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.\r
\r
@retval EFI_SUCCESS The new IP configuration has been configured successfully.\r
\r
ASSERT (Private->UsingIpv6);\r
Ip6Config = Private->Ip6Config;\r
- \r
+\r
//\r
- // Set the default gateway address. \r
+ // Set the default gateway address.\r
//\r
if (!Private->NoGateway && !NetIp6IsUnspecifiedAddr (&Private->GatewayIp.v6)) {\r
Status = Ip6Config->SetData (\r
\r
/**\r
This function will register the station IP address.\r
- \r
+\r
@param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.\r
\r
@retval EFI_SUCCESS The new IP address has been configured successfully.\r
EFI_IPv6_ADDRESS *Ip6Addr;\r
EFI_IPv6_ADDRESS GatewayAddr;\r
EFI_IP6_CONFIG_DATA Ip6CfgData;\r
- EFI_EVENT MappedEvt; \r
+ EFI_EVENT MappedEvt;\r
UINTN DataSize;\r
BOOLEAN IsAddressOk;\r
UINTN Index;\r
\r
ASSERT (Private->UsingIpv6);\r
- \r
+\r
MappedEvt = NULL;\r
IsAddressOk = FALSE;\r
Ip6Addr = NULL;\r
Ip6Cfg = Private->Ip6Config;\r
Ip6 = Private->Ip6;\r
- \r
+\r
ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));\r
CopyMem (&CfgAddr, &Private->StationIp.v6, sizeof (EFI_IPv6_ADDRESS));\r
ZeroMem (&Ip6CfgData, sizeof (EFI_IP6_CONFIG_DATA));\r
- \r
+\r
Ip6CfgData.AcceptIcmpErrors = TRUE;\r
Ip6CfgData.DefaultProtocol = IP6_ICMP;\r
Ip6CfgData.HopLimit = HTTP_BOOT_DEFAULT_HOPLIMIT;\r
Ip6CfgData.ReceiveTimeout = HTTP_BOOT_DEFAULT_LIFETIME;\r
Ip6CfgData.TransmitTimeout = HTTP_BOOT_DEFAULT_LIFETIME;\r
- \r
+\r
Status = Ip6->Configure (Ip6, &Ip6CfgData);\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
- \r
+\r
//\r
// Create a notify event to set address flag when DAD if IP6 driver succeeded.\r
//\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
- \r
+\r
//\r
// Set static host ip6 address. This is a asynchronous process.\r
//\r
Ip6ConfigDataTypeManualAddress,\r
sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS),\r
&CfgAddr\r
- ); \r
+ );\r
if (EFI_ERROR (Status) && Status != EFI_NOT_READY) {\r
goto ON_EXIT;\r
} else if (Status == EFI_NOT_READY) {\r
Status = EFI_DEVICE_ERROR;\r
goto ON_EXIT;\r
}\r
- \r
+\r
Ip6Addr = AllocatePool (DataSize);\r
if (Ip6Addr == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) {\r
Status = EFI_ABORTED;\r
goto ON_EXIT;\r
- } \r
+ }\r
}\r
- \r
+\r
ON_EXIT:\r
if (MappedEvt != NULL) {\r
Ip6Cfg->UnregisterDataNotify (\r
if (Ip6Addr != NULL) {\r
FreePool (Ip6Addr);\r
}\r
- \r
- return Status; \r
+\r
+ return Status;\r
}\r
\r
/**\r
//\r
OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);\r
ASSERT (OptCount >0);\r
- \r
+\r
Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));\r
if (Retransmit == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- \r
+\r
ZeroMem (&Mode, sizeof (EFI_DHCP6_MODE_DATA));\r
ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA));\r
- \r
+\r
Config.OptionCount = OptCount;\r
Config.OptionList = OptList;\r
Config.Dhcp6Callback = HttpBootDhcp6CallBack;\r
Retransmit->Mrc = 4;\r
Retransmit->Mrt = 32;\r
Retransmit->Mrd = 60;\r
- \r
+\r
//\r
// Configure the DHCPv6 instance for HTTP boot.\r
//\r
Private->SelectIndex = 0;\r
ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));\r
ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));\r
- \r
+\r
//\r
// Start DHCPv6 S.A.R.R. process to acquire IPv6 address.\r
//\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
- \r
+\r
//\r
// Get the acquired IPv6 address and store them.\r
//\r
if (EFI_ERROR (Status)) {\r
goto ON_EXIT;\r
}\r
- \r
+\r
ASSERT (Mode.Ia->State == Dhcp6Bound);\r
CopyMem (&Private->StationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
- \r
+\r
AsciiPrint ("\n Station IPv6 address is ");\r
HttpBootShowIp6Addr (&Private->StationIp.v6);\r
AsciiPrint ("\n");\r
- \r
+\r
ON_EXIT:\r
if (EFI_ERROR (Status)) {\r
Dhcp6->Stop (Dhcp6);\r
}\r
}\r
\r
- return Status; \r
- \r
+ return Status;\r
+\r
}\r
\r