Node->Ipv4.StaticIpAddress = FALSE;\r
CopyMem (&Node->Ipv4.GatewayIpAddress, &Private->GatewayIp, sizeof (EFI_IPv4_ADDRESS));\r
CopyMem (&Node->Ipv4.SubnetMask, &Private->SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
- \r
- TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
- FreePool (Node);\r
- if (TmpDevicePath == NULL) {\r
+ } else {\r
+ Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));\r
+ if (Node == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- } else {\r
- ASSERT (FALSE);\r
+ Node->Ipv6.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Node->Ipv6.Header.SubType = MSG_IPv6_DP;\r
+ SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH));\r
+ Node->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;\r
+ Node->Ipv6.RemotePort = Private->Port;\r
+ Node->Ipv6.Protocol = EFI_IP_PROTO_TCP; \r
+ Node->Ipv6.IpAddressOrigin = 0;\r
+ CopyMem (&Node->Ipv6.LocalIpAddress, &Private->StationIp.v6, sizeof (EFI_IPv6_ADDRESS));\r
+ CopyMem (&Node->Ipv6.RemoteIpAddress, &Private->ServerIp.v6, sizeof (EFI_IPv6_ADDRESS));\r
+ CopyMem (&Node->Ipv6.GatewayIpAddress, &Private->GatewayIp.v6, sizeof (EFI_IPv6_ADDRESS));\r
+ }\r
+ \r
+ TmpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
+ FreePool (Node);\r
+ if (TmpDevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
\r
//\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- //\r
- // Reinstall the device path protocol of the child handle.\r
- //\r
- Status = gBS->ReinstallProtocolInterface (\r
- Private->ChildHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- Private->DevicePath,\r
- NewDevicePath\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ if (!Private->UsingIpv6) {\r
+ //\r
+ // Reinstall the device path protocol of the child handle.\r
+ //\r
+ Status = gBS->ReinstallProtocolInterface (\r
+ Private->Ip4Nic->Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ Private->Ip4Nic->DevicePath,\r
+ NewDevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ FreePool (Private->Ip4Nic->DevicePath);\r
+ Private->Ip4Nic->DevicePath = NewDevicePath;\r
+ } else {\r
+ //\r
+ // Reinstall the device path protocol of the child handle.\r
+ //\r
+ Status = gBS->ReinstallProtocolInterface (\r
+ Private->Ip6Nic->Controller,\r
+ &gEfiDevicePathProtocolGuid,\r
+ Private->Ip6Nic->DevicePath,\r
+ NewDevicePath\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ FreePool (Private->Ip6Nic->DevicePath);\r
+ Private->Ip6Nic->DevicePath = NewDevicePath;\r
}\r
\r
- FreePool (Private->DevicePath);\r
- Private->DevicePath = NewDevicePath;\r
return EFI_SUCCESS;\r
}\r
\r
\r
**/\r
EFI_STATUS\r
-HttpBootExtractUriInfo (\r
+HttpBootDhcp4ExtractUriInfo (\r
IN HTTP_BOOT_PRIVATE_DATA *Private\r
)\r
{\r
return Status;\r
}\r
\r
+/**\r
+ Parse the boot file URI information from the selected Dhcp6 offer packet.\r
+\r
+ @param[in] Private The pointer to the driver's private data.\r
+\r
+ @retval EFI_SUCCESS Successfully parsed out all the boot information.\r
+ @retval Others Failed to parse out the boot information.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootDhcp6ExtractUriInfo (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ HTTP_BOOT_DHCP6_PACKET_CACHE *SelectOffer;\r
+ HTTP_BOOT_DHCP6_PACKET_CACHE *HttpOffer;\r
+ UINT32 SelectIndex;\r
+ UINT32 ProxyIndex;\r
+ EFI_DHCP6_PACKET_OPTION *Option;\r
+ EFI_IPv6_ADDRESS IpAddr;\r
+ CHAR8 *HostName;\r
+ CHAR16 *HostNameStr;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (Private != NULL);\r
+ ASSERT (Private->SelectIndex != 0);\r
+ SelectIndex = Private->SelectIndex - 1;\r
+ ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM);\r
+\r
+ Status = EFI_SUCCESS;\r
+ HostName = NULL;\r
+ //\r
+ // SelectOffer contains the IP address configuration and name server configuration.\r
+ // HttpOffer contains the boot file URL.\r
+ //\r
+ SelectOffer = &Private->OfferBuffer[SelectIndex].Dhcp6;\r
+ if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || (SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) {\r
+ HttpOffer = SelectOffer;\r
+ } else {\r
+ ASSERT (Private->SelectProxyType != HttpOfferTypeMax);\r
+ ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];\r
+ HttpOffer = &Private->OfferBuffer[ProxyIndex].Dhcp6;\r
+ }\r
+\r
+ //\r
+ // Set the Local station address to IP layer.\r
+ //\r
+ Status = HttpBootSetIp6Address (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Configure the default DNS server if server assigned.\r
+ //\r
+ if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || (SelectOffer->OfferType == HttpOfferTypeDhcpDns)) {\r
+ Option = SelectOffer->OptList[HTTP_BOOT_DHCP6_IDX_DNS_SERVER];\r
+ ASSERT (Option != NULL);\r
+ Status = HttpBootSetIp6Dns (\r
+ Private,\r
+ HTONS (Option->OpLen),\r
+ Option->Data\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ //\r
+ // Extract the HTTP server Ip frome URL. This is used to Check route table \r
+ // whether can send message to HTTP Server Ip through the GateWay.\r
+ //\r
+ Status = HttpUrlGetIp6 (\r
+ (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,\r
+ HttpOffer->UriParser,\r
+ &IpAddr\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // The Http server address is expressed by Name Ip, so perform DNS resolution\r
+ //\r
+ Status = HttpUrlGetHostName (\r
+ (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,\r
+ HttpOffer->UriParser,\r
+ &HostName\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (CHAR16));\r
+ if (HostNameStr == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Error;\r
+ }\r
+ \r
+ AsciiStrToUnicodeStr (HostName, HostNameStr);\r
+ Status = HttpBootDns (Private, HostNameStr, &IpAddr);\r
+ FreePool (HostNameStr);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ } \r
+ } \r
+ \r
+ CopyMem (&Private->ServerIp.v6, &IpAddr, sizeof (EFI_IPv6_ADDRESS)); \r
+ \r
+ //\r
+ // register the IPv6 gateway address to the network device.\r
+ //\r
+ Status = HttpBootSetIp6Gateway (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Extract the port from URL, and use default HTTP port 80 if not provided.\r
+ //\r
+ Status = HttpUrlGetPort (\r
+ (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,\r
+ HttpOffer->UriParser,\r
+ &Private->Port\r
+ );\r
+ if (EFI_ERROR (Status) || Private->Port == 0) {\r
+ Private->Port = 80;\r
+ }\r
+ \r
+ //\r
+ // Record the URI of boot file from the selected HTTP offer.\r
+ //\r
+ Private->BootFileUriParser = HttpOffer->UriParser;\r
+ Private->BootFileUri = (CHAR8*) HttpOffer->OptList[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data;\r
+\r
+ \r
+ //\r
+ // All boot informations are valid here.\r
+ //\r
+ AsciiPrint ("\n URI: %a", Private->BootFileUri);\r
+ //\r
+ // Update the device path to include the IP and boot URI information.\r
+ //\r
+ Status = HttpBootUpdateDevicePath (Private);\r
+\r
+Error:\r
+ \r
+ if (HostName != NULL) {\r
+ FreePool (HostName);\r
+ }\r
+ \r
+ return Status;\r
+}\r
+\r
+\r
/**\r
Discover all the boot information for boot file.\r
\r
}\r
\r
if (!Private->UsingIpv6) {\r
- Status = HttpBootExtractUriInfo (Private);\r
+ Status = HttpBootDhcp4ExtractUriInfo (Private);\r
} else {\r
- ASSERT (FALSE);\r
+ Status = HttpBootDhcp6ExtractUriInfo (Private);\r
}\r
\r
return Status;\r
\r
ZeroMem (&ConfigData, sizeof (HTTP_IO_CONFIG_DATA));\r
if (!Private->UsingIpv6) {\r
- ConfigData.Config4.HttpVersion = HttpVersion11;\r
+ ConfigData.Config4.HttpVersion = HttpVersion11;\r
ConfigData.Config4.RequestTimeOut = HTTP_BOOT_REQUEST_TIMEOUT;\r
IP4_COPY_ADDRESS (&ConfigData.Config4.LocalIp, &Private->StationIp.v4);\r
IP4_COPY_ADDRESS (&ConfigData.Config4.SubnetMask, &Private->SubnetMask.v4);\r
} else {\r
- ASSERT (FALSE);\r
+ ConfigData.Config6.HttpVersion = HttpVersion11;\r
+ ConfigData.Config6.RequestTimeOut = HTTP_BOOT_REQUEST_TIMEOUT;\r
+ IP6_COPY_ADDRESS (&ConfigData.Config6.LocalIp, &Private->StationIp.v6);\r
}\r
\r
Status = HttpIoCreateIo (\r
\r
NicHandle = HttpBootGetNicByIp4Children (ControllerHandle);\r
if (NicHandle == NULL) {\r
- return EFI_UNSUPPORTED;\r
+ NicHandle = HttpBootGetNicByIp6Children(ControllerHandle);\r
+ if (NicHandle == NULL) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
}\r
\r
//\r
}\r
\r
//\r
- // The offer with "HttpClient" is a Http offer.\r
+ // The offer with "HTTPClient" is a Http offer.\r
//\r
Option = Options[HTTP_BOOT_DHCP4_TAG_INDEX_CLASS_ID];\r
if ((Option != NULL) && (Option->Length >= 9) &&\r
}\r
\r
/**\r
- Select an DHCPv4 offer, and record SelectIndex and SelectProxyType.\r
+ Select an DHCPv4 or DHCP6 offer, and record SelectIndex and SelectProxyType.\r
\r
@param[in] Private Pointer to HTTP boot driver private data.\r
\r
**/\r
VOID\r
-HttpBootSelectDhcp4Offer (\r
+HttpBootSelectDhcpOffer (\r
IN HTTP_BOOT_PRIVATE_DATA *Private\r
)\r
{\r
// Select offer according to the priority in UEFI spec, and record the SelectIndex \r
// and SelectProxyType.\r
//\r
- HttpBootSelectDhcp4Offer (Private);\r
+ HttpBootSelectDhcpOffer (Private);\r
\r
if (Private->SelectIndex == 0) {\r
Status = EFI_ABORTED;\r
\r
**/\r
EFI_STATUS\r
-HttpBootSetIpPolicy (\r
+HttpBootSetIp4Policy (\r
IN HTTP_BOOT_PRIVATE_DATA *Private\r
)\r
{\r
Dhcp4 = Private->Dhcp4;\r
ASSERT (Dhcp4 != NULL);\r
\r
- Status = HttpBootSetIpPolicy (Private);\r
+ Status = HttpBootSetIp4Policy (Private);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
EFI_DHCP4_PACKET_OPTION *OptList[HTTP_BOOT_DHCP4_TAG_INDEX_MAX];\r
} HTTP_BOOT_DHCP4_PACKET_CACHE;\r
\r
+/**\r
+ Select an DHCPv4 or DHCP6 offer, and record SelectIndex and SelectProxyType.\r
+\r
+ @param[in] Private Pointer to HTTP boot driver private data.\r
+\r
+**/\r
+VOID\r
+HttpBootSelectDhcpOffer (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ );\r
+\r
/**\r
Start the D.O.R.A DHCPv4 process to acquire the IPv4 address and other Http boot information.\r
\r
--- /dev/null
+/** @file\r
+ Functions implementation related with DHCPv6 for HTTP boot driver.\r
+\r
+Copyright (c) 2015, 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
+\r
+**/\r
+\r
+#include "HttpBootDxe.h"\r
+\r
+/**\r
+ Build the options buffer for the DHCPv6 request packet.\r
+\r
+ @param[in] Private The pointer to HTTP BOOT driver private data.\r
+ @param[out] OptList The pointer to the option pointer array.\r
+ @param[in] Buffer The pointer to the buffer to contain the option list.\r
+\r
+ @return Index The count of the built-in options.\r
+\r
+**/\r
+UINT32\r
+HttpBootBuildDhcp6Options (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ OUT EFI_DHCP6_PACKET_OPTION **OptList,\r
+ IN UINT8 *Buffer\r
+ )\r
+{\r
+ HTTP_BOOT_DHCP6_OPTION_ENTRY OptEnt;\r
+ UINT16 Value;\r
+ UINT32 Index;\r
+\r
+ Index = 0;\r
+ OptList[0] = (EFI_DHCP6_PACKET_OPTION *) Buffer;\r
+\r
+ //\r
+ // Append client option request option\r
+ //\r
+ OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_ORO);\r
+ OptList[Index]->OpLen = HTONS (8);\r
+ OptEnt.Oro = (HTTP_BOOT_DHCP6_OPTION_ORO *) OptList[Index]->Data;\r
+ OptEnt.Oro->OpCode[0] = HTONS(HTTP_BOOT_DHCP6_OPT_BOOT_FILE_URL);\r
+ OptEnt.Oro->OpCode[1] = HTONS(HTTP_BOOT_DHCP6_OPT_BOOT_FILE_PARAM);\r
+ OptEnt.Oro->OpCode[2] = HTONS(HTTP_BOOT_DHCP6_OPT_DNS_SERVERS);\r
+ OptEnt.Oro->OpCode[3] = HTONS(HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS);\r
+ Index++;\r
+ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
+\r
+ //\r
+ // Append client network device interface option\r
+ //\r
+ OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_UNDI);\r
+ OptList[Index]->OpLen = HTONS ((UINT16)3);\r
+ OptEnt.Undi = (HTTP_BOOT_DHCP6_OPTION_UNDI *) OptList[Index]->Data;\r
+\r
+ if (Private->Nii != NULL) {\r
+ OptEnt.Undi->Type = Private->Nii->Type;\r
+ OptEnt.Undi->MajorVer = Private->Nii->MajorVer;\r
+ OptEnt.Undi->MinorVer = Private->Nii->MinorVer;\r
+ } else {\r
+ OptEnt.Undi->Type = DEFAULT_UNDI_TYPE;\r
+ OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR;\r
+ OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR;\r
+ }\r
+\r
+ Index++;\r
+ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
+\r
+ //\r
+ // Append client system architecture option\r
+ //\r
+ OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_ARCH);\r
+ OptList[Index]->OpLen = HTONS ((UINT16) sizeof (HTTP_BOOT_DHCP6_OPTION_ARCH));\r
+ OptEnt.Arch = (HTTP_BOOT_DHCP6_OPTION_ARCH *) OptList[Index]->Data;\r
+ Value = HTONS (EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE);\r
+ CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16));\r
+ Index++;\r
+ OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);\r
+\r
+ //\r
+ // Append vendor class identify option.\r
+ //\r
+ OptList[Index]->OpCode = HTONS (HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS);\r
+ OptList[Index]->OpLen = HTONS ((UINT16) sizeof (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS));\r
+ OptEnt.VendorClass = (HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS *) OptList[Index]->Data;\r
+ OptEnt.VendorClass->Vendor = HTONL (HTTP_BOOT_DHCP6_ENTERPRISE_NUM);\r
+ OptEnt.VendorClass->ClassLen = HTONS ((UINT16) sizeof (HTTP_BOOT_CLASS_ID));\r
+ CopyMem (\r
+ &OptEnt.VendorClass->ClassId,\r
+ DEFAULT_CLASS_ID_DATA,\r
+ sizeof (HTTP_BOOT_CLASS_ID)\r
+ );\r
+ HttpBootUintnToAscDecWithFormat (\r
+ EFI_HTTP_BOOT_CLIENT_SYSTEM_ARCHITECTURE,\r
+ OptEnt.VendorClass->ClassId.ArchitectureType,\r
+ sizeof (OptEnt.VendorClass->ClassId.ArchitectureType)\r
+ );\r
+\r
+ if (Private->Nii != NULL) {\r
+ CopyMem (\r
+ OptEnt.VendorClass->ClassId.InterfaceName,\r
+ Private->Nii->StringId,\r
+ sizeof (OptEnt.VendorClass->ClassId.InterfaceName)\r
+ );\r
+ HttpBootUintnToAscDecWithFormat (\r
+ Private->Nii->MajorVer,\r
+ OptEnt.VendorClass->ClassId.UndiMajor,\r
+ sizeof (OptEnt.VendorClass->ClassId.UndiMajor)\r
+ );\r
+ HttpBootUintnToAscDecWithFormat (\r
+ Private->Nii->MinorVer,\r
+ OptEnt.VendorClass->ClassId.UndiMinor,\r
+ sizeof (OptEnt.VendorClass->ClassId.UndiMinor)\r
+ );\r
+ }\r
+\r
+ Index++;\r
+\r
+ return Index;\r
+}\r
+\r
+/**\r
+ Parse out a DHCPv6 option by OptTag, and find the position in buffer.\r
+\r
+ @param[in] Buffer The pointer to the option buffer.\r
+ @param[in] Length Length of the option buffer.\r
+ @param[in] OptTag The required option tag.\r
+\r
+ @retval NULL Failed to parse the required option.\r
+ @retval Others The postion of the required option in buffer.\r
+\r
+**/\r
+EFI_DHCP6_PACKET_OPTION *\r
+HttpBootParseDhcp6Options (\r
+ IN UINT8 *Buffer,\r
+ IN UINT32 Length,\r
+ IN UINT16 OptTag\r
+ )\r
+{\r
+ EFI_DHCP6_PACKET_OPTION *Option;\r
+ UINT32 Offset;\r
+\r
+ Option = (EFI_DHCP6_PACKET_OPTION *) Buffer;\r
+ Offset = 0;\r
+\r
+ //\r
+ // OpLen and OpCode here are both stored in network order.\r
+ //\r
+ while (Offset < Length) {\r
+\r
+ if (NTOHS (Option->OpCode) == OptTag) {\r
+\r
+ return Option;\r
+ }\r
+\r
+ Offset += (NTOHS(Option->OpLen) + 4);\r
+ Option = (EFI_DHCP6_PACKET_OPTION *) (Buffer + Offset);\r
+ }\r
+\r
+ return NULL;\r
+\r
+}\r
+\r
+/**\r
+ Parse the cached DHCPv6 packet, including all the options.\r
+\r
+ @param[in] Cache6 The pointer to a cached DHCPv6 packet.\r
+\r
+ @retval EFI_SUCCESS Parsed the DHCPv6 packet successfully.\r
+ @retval EFI_DEVICE_ERROR Failed to parse and invalid the packet.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootParseDhcp6Packet (\r
+ IN HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6\r
+ )\r
+{\r
+ EFI_DHCP6_PACKET *Offer;\r
+ EFI_DHCP6_PACKET_OPTION **Options;\r
+ EFI_DHCP6_PACKET_OPTION *Option;\r
+ HTTP_BOOT_OFFER_TYPE OfferType;\r
+ EFI_IPv6_ADDRESS IpAddr;\r
+ BOOLEAN IsProxyOffer;\r
+ BOOLEAN IsHttpOffer;\r
+ BOOLEAN IsDnsOffer;\r
+ BOOLEAN IpExpressedUri;\r
+ EFI_STATUS Status;\r
+ UINT32 Offset;\r
+ UINT32 Length;\r
+ \r
+ IsDnsOffer = FALSE;\r
+ IpExpressedUri = FALSE;\r
+ IsProxyOffer = TRUE;\r
+ IsHttpOffer = FALSE;\r
+ Offer = &Cache6->Packet.Offer;\r
+ Options = Cache6->OptList;\r
+ \r
+ ZeroMem (Cache6->OptList, sizeof (Cache6->OptList));\r
+\r
+ Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option);\r
+ Offset = 0;\r
+ Length = GET_DHCP6_OPTION_SIZE (Offer);\r
+\r
+ //\r
+ // OpLen and OpCode here are both stored in network order, since they are from original packet.\r
+ //\r
+ while (Offset < Length) {\r
+\r
+ if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_IA_NA) {\r
+ Options[HTTP_BOOT_DHCP6_IDX_IA_NA] = Option;\r
+ } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_BOOT_FILE_URL) {\r
+ //\r
+ // The server sends this option to inform the client about an URL to a boot file.\r
+ //\r
+ Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] = Option;\r
+ } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_BOOT_FILE_PARAM) {\r
+ Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_PARAM] = Option;\r
+ } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS) {\r
+ Options[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS] = Option;\r
+ } else if (NTOHS (Option->OpCode) == HTTP_BOOT_DHCP6_OPT_DNS_SERVERS) {\r
+ Options[HTTP_BOOT_DHCP6_IDX_DNS_SERVER] = Option;\r
+ }\r
+\r
+ Offset += (NTOHS (Option->OpLen) + 4);\r
+ Option = (EFI_DHCP6_PACKET_OPTION *) (Offer->Dhcp6.Option + Offset);\r
+ }\r
+ //\r
+ // The offer with assigned client address is NOT a proxy offer.\r
+ // An ia_na option, embeded with valid ia_addr option and a status_code of success.\r
+ //\r
+ Option = Options[HTTP_BOOT_DHCP6_IDX_IA_NA];\r
+ if (Option != NULL) {\r
+ Option = HttpBootParseDhcp6Options (\r
+ Option->Data + 12,\r
+ NTOHS (Option->OpLen),\r
+ HTTP_BOOT_DHCP6_OPT_STATUS_CODE\r
+ );\r
+ if ((Option != NULL && Option->Data[0] == 0) || (Option == NULL)) {\r
+ IsProxyOffer = FALSE;\r
+ }\r
+ }\r
+\r
+ //\r
+ // The offer with "HTTPClient" is a Http offer.\r
+ //\r
+ Option = Options[HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS];\r
+\r
+ if (Option != NULL &&\r
+ NTOHS(Option->OpLen) >= 10 &&\r
+ CompareMem (Option->Data, DEFAULT_CLASS_ID_DATA, 10) == 0) {\r
+ IsHttpOffer = TRUE;\r
+ }\r
+\r
+ //\r
+ // The offer with Domain Server is a DNS offer.\r
+ //\r
+ Option = Options[HTTP_BOOT_DHCP6_IDX_DNS_SERVER];\r
+ if (Option != NULL) {\r
+ IsDnsOffer = TRUE;\r
+ }\r
+\r
+ //\r
+ // Http offer must have a boot URI.\r
+ //\r
+ if (IsHttpOffer && Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL] == NULL) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ \r
+ //\r
+ // Try to retrieve the IP of HTTP server from URI. \r
+ //\r
+ if (IsHttpOffer) {\r
+ Status = HttpParseUrl (\r
+ (CHAR8*) Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,\r
+ (UINT32) AsciiStrLen ((CHAR8*) Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data),\r
+ FALSE,\r
+ &Cache6->UriParser\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ Status = HttpUrlGetIp6 (\r
+ (CHAR8*) Options[HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL]->Data,\r
+ Cache6->UriParser,\r
+ &IpAddr\r
+ );\r
+ IpExpressedUri = !EFI_ERROR (Status);\r
+ }\r
+\r
+ //\r
+ // Determine offer type of the DHCPv6 packet.\r
+ //\r
+ if (IsHttpOffer) {\r
+ if (IpExpressedUri) {\r
+ OfferType = IsProxyOffer ? HttpOfferTypeProxyIpUri : HttpOfferTypeDhcpIpUri;\r
+ } else {\r
+ if (!IsProxyOffer) {\r
+ OfferType = IsDnsOffer ? HttpOfferTypeDhcpNameUriDns : HttpOfferTypeDhcpNameUri;\r
+ } else {\r
+ OfferType = HttpOfferTypeProxyNameUri;\r
+ }\r
+ }\r
+\r
+ } else {\r
+ if (!IsProxyOffer) {\r
+ OfferType = IsDnsOffer ? HttpOfferTypeDhcpDns : HttpOfferTypeDhcpOnly;\r
+ } else {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+ \r
+ Cache6->OfferType = OfferType;\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Cache the DHCPv6 packet.\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
+**/\r
+VOID\r
+HttpBootCacheDhcp6Packet (\r
+ IN EFI_DHCP6_PACKET *Dst,\r
+ IN EFI_DHCP6_PACKET *Src\r
+ )\r
+{\r
+ ASSERT (Dst->Size >= Src->Length);\r
+\r
+ CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length);\r
+ Dst->Length = Src->Length;\r
+}\r
+\r
+/**\r
+ Cache all the received DHCPv6 offers, and set OfferIndex and OfferCount.\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
+**/\r
+VOID\r
+HttpBootCacheDhcp6Offer (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN EFI_DHCP6_PACKET *RcvdOffer\r
+ )\r
+{\r
+ HTTP_BOOT_DHCP6_PACKET_CACHE *Cache6;\r
+ EFI_DHCP6_PACKET *Offer;\r
+ HTTP_BOOT_OFFER_TYPE OfferType;\r
+\r
+ Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6;\r
+ Offer = &Cache6->Packet.Offer;\r
+\r
+ //\r
+ // Cache the content of DHCPv6 packet firstly.\r
+ //\r
+ HttpBootCacheDhcp6Packet(Offer, RcvdOffer);\r
+\r
+ //\r
+ // Validate the DHCPv6 packet, and parse the options and offer type.\r
+ //\r
+ if (EFI_ERROR (HttpBootParseDhcp6Packet (Cache6))) {\r
+ return ;\r
+ }\r
+\r
+ //\r
+ // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.\r
+ //\r
+ OfferType = Cache6->OfferType;\r
+ ASSERT (OfferType < HttpOfferTypeMax);\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
+}\r
+\r
+/**\r
+ EFI_DHCP6_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol driver\r
+ to intercept events that occurred in the configuration process.\r
+\r
+ @param[in] This The pointer to the EFI DHCPv6 Protocol.\r
+ @param[in] Context The pointer to the context set by EFI_DHCP6_PROTOCOL.Configure().\r
+ @param[in] CurrentState The current operational state of the EFI DHCPv Protocol driver.\r
+ @param[in] Dhcp6Event The event that occurs in the current state, which usually means a\r
+ state transition.\r
+ @param[in] Packet The DHCPv6 packet that is going to be sent or was already received.\r
+ @param[out] NewPacket The packet that is used to replace the Packet above.\r
+\r
+ @retval EFI_SUCCESS Told the EFI DHCPv6 Protocol driver to continue the DHCP process.\r
+ @retval EFI_NOT_READY Only used in the Dhcp6Selecting state. The EFI DHCPv6 Protocol\r
+ driver will continue to wait for more packets.\r
+ @retval EFI_ABORTED Told the EFI DHCPv6 Protocol driver to abort the current process.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootDhcp6CallBack (\r
+ IN EFI_DHCP6_PROTOCOL *This,\r
+ IN VOID *Context,\r
+ IN EFI_DHCP6_STATE CurrentState,\r
+ IN EFI_DHCP6_EVENT Dhcp6Event,\r
+ IN EFI_DHCP6_PACKET *Packet,\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
+ ASSERT (*NewPacket != NULL);\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
+ 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
+ @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.\r
+ @param[in] TimeOutInSecond Timeout value in seconds.\r
+ @param[out] GatewayAddr Pointer to store the gateway IP address.\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
+EFI_STATUS\r
+HttpBootCheckRouteTable (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN UINTN TimeOutInSecond,\r
+ OUT EFI_IPv6_ADDRESS *GatewayAddr\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IP6_PROTOCOL *Ip6;\r
+ EFI_IP6_MODE_DATA Ip6ModeData;\r
+ UINTN Index;\r
+ EFI_EVENT TimeOutEvt;\r
+ UINTN RetryCount;\r
+ BOOLEAN GatewayIsFound;\r
+\r
+ ASSERT (GatewayAddr != NULL);\r
+ ASSERT (Private != NULL);\r
+\r
+ Ip6 = Private->Ip6;\r
+ GatewayIsFound = FALSE;\r
+ RetryCount = 0;\r
+ TimeOutEvt = NULL;\r
+ Status = EFI_SUCCESS;\r
+ ZeroMem (GatewayAddr, sizeof (EFI_IPv6_ADDRESS));\r
+\r
+ while (TRUE) {\r
+ Status = Ip6->GetModeData (Ip6, &Ip6ModeData, NULL, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ //\r
+ // Find out the gateway address which can route the message which send to ServerIp.\r
+ //\r
+ for (Index = 0; Index < Ip6ModeData.RouteCount; Index++) {\r
+ if (NetIp6IsNetEqual (&Private->ServerIp.v6, &Ip6ModeData.RouteTable[Index].Destination, Ip6ModeData.RouteTable[Index].PrefixLength)) {\r
+ IP6_COPY_ADDRESS (GatewayAddr, &Ip6ModeData.RouteTable[Index].Gateway);\r
+ GatewayIsFound = TRUE;\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Ip6ModeData.AddressList != NULL) {\r
+ FreePool (Ip6ModeData.AddressList);\r
+ }\r
+ if (Ip6ModeData.GroupTable != NULL) {\r
+ FreePool (Ip6ModeData.GroupTable);\r
+ }\r
+ if (Ip6ModeData.RouteTable != NULL) {\r
+ FreePool (Ip6ModeData.RouteTable);\r
+ }\r
+ if (Ip6ModeData.NeighborCache != NULL) {\r
+ FreePool (Ip6ModeData.NeighborCache);\r
+ }\r
+ if (Ip6ModeData.PrefixTable != NULL) {\r
+ FreePool (Ip6ModeData.PrefixTable);\r
+ }\r
+ if (Ip6ModeData.IcmpTypeList != NULL) {\r
+ FreePool (Ip6ModeData.IcmpTypeList);\r
+ }\r
+ \r
+ if (GatewayIsFound || RetryCount == TimeOutInSecond) {\r
+ break;\r
+ }\r
+ \r
+ RetryCount++;\r
+ \r
+ //\r
+ // Delay 1 second then recheck it again.\r
+ //\r
+ if (TimeOutEvt == NULL) {\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER,\r
+ TPL_CALLBACK,\r
+ NULL,\r
+ NULL,\r
+ &TimeOutEvt\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ }\r
+\r
+ Status = gBS->SetTimer (TimeOutEvt, TimerRelative, TICKS_PER_SECOND);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {\r
+ Ip6->Poll (Ip6);\r
+ }\r
+ }\r
+ \r
+ON_EXIT:\r
+ if (TimeOutEvt != NULL) {\r
+ gBS->CloseEvent (TimeOutEvt);\r
+ }\r
+ \r
+ if (GatewayIsFound) {\r
+ Status = EFI_SUCCESS;\r
+ } else if (RetryCount == TimeOutInSecond) {\r
+ Status = EFI_TIMEOUT;\r
+ }\r
+\r
+ return Status; \r
+}\r
+\r
+/**\r
+ Set the IP6 policy to Automatic.\r
+\r
+ @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.\r
+\r
+ @retval EFI_SUCCESS Switch the IP policy succesfully.\r
+ @retval Others Unexpect error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Policy (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_IP6_CONFIG_POLICY Policy;\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
+ EFI_STATUS Status;\r
+ UINTN DataSize;\r
+\r
+ Ip6Config = Private->Ip6Config;\r
+ DataSize = sizeof (EFI_IP6_CONFIG_POLICY);\r
+ \r
+ //\r
+ // Get and store the current policy of IP6 driver.\r
+ //\r
+ Status = Ip6Config->GetData (\r
+ Ip6Config,\r
+ Ip6ConfigDataTypePolicy,\r
+ &DataSize,\r
+ &Policy\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if (Policy == Ip6ConfigPolicyManual) {\r
+ Policy = Ip6ConfigPolicyAutomatic;\r
+ Status = Ip6Config->SetData (\r
+ Ip6Config,\r
+ Ip6ConfigDataTypePolicy,\r
+ sizeof(EFI_IP6_CONFIG_POLICY),\r
+ &Policy\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function will register the default DNS addresses to the network device.\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
+ of EFI_IPv6_ADDRESS instances.\r
+\r
+ @retval EFI_SUCCESS The DNS configuration has been configured successfully.\r
+ @retval Others Failed to configure the address.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Dns (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN UINTN DataLength,\r
+ IN VOID *DnsServerData\r
+ )\r
+{\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
+ \r
+ ASSERT (Private->UsingIpv6);\r
+\r
+ Ip6Config = Private->Ip6Config;\r
+ \r
+ return Ip6Config->SetData (\r
+ Ip6Config,\r
+ Ip6ConfigDataTypeDnsServer,\r
+ DataLength,\r
+ DnsServerData\r
+ );\r
+}\r
+\r
+/**\r
+ This function will register the IPv6 gateway address to the network device.\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
+ @retval Others Failed to configure the address.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Gateway (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
+ EFI_STATUS Status;\r
+\r
+ ASSERT (Private->UsingIpv6);\r
+ Ip6Config = Private->Ip6Config;\r
+ \r
+ //\r
+ // Set the default gateway address. \r
+ //\r
+ if (!Private->NoGateway && !NetIp6IsUnspecifiedAddr (&Private->GatewayIp.v6)) {\r
+ Status = Ip6Config->SetData (\r
+ Ip6Config,\r
+ Ip6ConfigDataTypeGateway,\r
+ sizeof (EFI_IPv6_ADDRESS),\r
+ &Private->GatewayIp.v6\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This function will register the station IP address.\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
+ @retval Others Failed to configure the address.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Address (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_IP6_PROTOCOL *Ip6;\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;\r
+ EFI_IP6_CONFIG_POLICY Policy;\r
+ EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr;\r
+ EFI_IPv6_ADDRESS *Ip6Addr;\r
+ EFI_IPv6_ADDRESS GatewayAddr;\r
+ EFI_IP6_CONFIG_DATA Ip6CfgData;\r
+ EFI_EVENT MappedEvt; \r
+ UINTN DataSize;\r
+ BOOLEAN IsAddressOk;\r
+ UINTN Index;\r
+\r
+ ASSERT (Private->UsingIpv6);\r
+ \r
+ MappedEvt = NULL;\r
+ IsAddressOk = FALSE;\r
+ Ip6Addr = NULL;\r
+ Ip6Cfg = Private->Ip6Config;\r
+ Ip6 = Private->Ip6;\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
+ 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
+ Status = Ip6->Configure (Ip6, &Ip6CfgData);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ //\r
+ // Retrieve the gateway address from IP6 route table.\r
+ //\r
+ Status = HttpBootCheckRouteTable (Private, HTTP_BOOT_IP6_ROUTE_TABLE_TIMEOUT, &GatewayAddr);\r
+ if (EFI_ERROR (Status)) {\r
+ Private->NoGateway = TRUE;\r
+ } else {\r
+ IP6_COPY_ADDRESS (&Private->GatewayIp.v6, &GatewayAddr);\r
+ }\r
+\r
+ //\r
+ // Set the new address by Ip6ConfigProtocol manually.\r
+ //\r
+ Policy = Ip6ConfigPolicyManual;\r
+ Status = Ip6Cfg->SetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypePolicy,\r
+ sizeof(EFI_IP6_CONFIG_POLICY),\r
+ &Policy\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ //\r
+ // Create a notify event to set address flag when DAD if IP6 driver succeeded.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpBootCommonNotify,\r
+ &IsAddressOk,\r
+ &MappedEvt\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ //\r
+ // Set static host ip6 address. This is a asynchronous process.\r
+ //\r
+ Status = Ip6Cfg->RegisterDataNotify (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeManualAddress,\r
+ MappedEvt\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ Status = Ip6Cfg->SetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeManualAddress,\r
+ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS),\r
+ &CfgAddr\r
+ ); \r
+ if (EFI_ERROR (Status) && Status != EFI_NOT_READY) {\r
+ goto ON_EXIT;\r
+ } else if (Status == EFI_NOT_READY) {\r
+ //\r
+ // Poll the network until the asynchronous process is finished.\r
+ //\r
+ while (!IsAddressOk) {\r
+ Ip6->Poll (Ip6);\r
+ }\r
+ //\r
+ // Check whether the Ip6 Address setting is successed.\r
+ //\r
+ DataSize = 0;\r
+ Status = Ip6Cfg->GetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeManualAddress,\r
+ &DataSize,\r
+ NULL\r
+ );\r
+ if (Status != EFI_BUFFER_TOO_SMALL || DataSize == 0) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ Ip6Addr = AllocatePool (DataSize);\r
+ if (Ip6Addr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Status = Ip6Cfg->GetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeManualAddress,\r
+ &DataSize,\r
+ (VOID *) Ip6Addr\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto ON_EXIT;\r
+ }\r
+\r
+ for (Index = 0; Index < DataSize / sizeof (EFI_IPv6_ADDRESS); Index ++) {\r
+ if (CompareMem (Ip6Addr + Index, &CfgAddr, sizeof (EFI_IPv6_ADDRESS)) == 0) {\r
+ break;\r
+ }\r
+ }\r
+ if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) {\r
+ Status = EFI_ABORTED;\r
+ goto ON_EXIT;\r
+ } \r
+ }\r
+ \r
+ON_EXIT:\r
+ if (MappedEvt != NULL) {\r
+ Ip6Cfg->UnregisterDataNotify (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeManualAddress,\r
+ MappedEvt\r
+ );\r
+ gBS->CloseEvent (MappedEvt);\r
+ }\r
+\r
+ if (Ip6Addr != NULL) {\r
+ FreePool (Ip6Addr);\r
+ }\r
+ \r
+ return Status; \r
+}\r
+\r
+/**\r
+ Start the S.A.R.R DHCPv6 process to acquire the IPv6 address and other Http boot information.\r
+\r
+ @param[in] Private Pointer to HTTP_BOOT private data.\r
+\r
+ @retval EFI_SUCCESS The S.A.R.R process successfully finished.\r
+ @retval Others Failed to finish the S.A.R.R process.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootDhcp6Sarr (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ EFI_DHCP6_PROTOCOL *Dhcp6;\r
+ EFI_DHCP6_CONFIG_DATA Config;\r
+ EFI_DHCP6_MODE_DATA Mode;\r
+ EFI_DHCP6_RETRANSMISSION *Retransmit;\r
+ EFI_DHCP6_PACKET_OPTION *OptList[HTTP_BOOT_DHCP6_OPTION_MAX_NUM];\r
+ UINT32 OptCount;\r
+ UINT8 Buffer[HTTP_BOOT_DHCP6_OPTION_MAX_SIZE];\r
+ EFI_STATUS Status;\r
+\r
+ Dhcp6 = Private->Dhcp6;\r
+ ASSERT (Dhcp6 != NULL);\r
+\r
+ //\r
+ // Build options list for the request packet.\r
+ //\r
+ OptCount = HttpBootBuildDhcp6Options (Private, OptList, Buffer);\r
+ ASSERT (OptCount >0);\r
+ \r
+ Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));\r
+ if (Retransmit == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ ZeroMem (&Mode, sizeof (EFI_DHCP6_MODE_DATA));\r
+ ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA));\r
+ \r
+ Config.OptionCount = OptCount;\r
+ Config.OptionList = OptList;\r
+ Config.Dhcp6Callback = HttpBootDhcp6CallBack;\r
+ Config.CallbackContext = Private;\r
+ Config.IaInfoEvent = NULL;\r
+ Config.RapidCommit = FALSE;\r
+ Config.ReconfigureAccept = FALSE;\r
+ Config.IaDescriptor.IaId = NET_RANDOM (NetRandomInitSeed ());\r
+ Config.IaDescriptor.Type = EFI_DHCP6_IA_TYPE_NA;\r
+ Config.SolicitRetransmission = Retransmit;\r
+ Retransmit->Irt = 4;\r
+ Retransmit->Mrc = 4;\r
+ Retransmit->Mrt = 32;\r
+ Retransmit->Mrd = 60;\r
+ \r
+ //\r
+ // Configure the DHCPv6 instance for HTTP boot.\r
+ //\r
+ Status = Dhcp6->Configure (Dhcp6, &Config);\r
+ FreePool (Retransmit);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ //\r
+ // Initialize the record fields for DHCPv6 offer in private data.\r
+ //\r
+ Private->OfferNum = 0;\r
+ Private->SelectIndex = 0;\r
+ ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));\r
+ ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));\r
+ \r
+ //\r
+ // Start DHCPv6 S.A.R.R. process to acquire IPv6 address.\r
+ //\r
+ Status = Dhcp6->Start (Dhcp6);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ //\r
+ // Get the acquired IPv6 address and store them.\r
+ //\r
+ Status = Dhcp6->GetModeData (Dhcp6, &Mode, NULL);\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+ \r
+ ASSERT (Mode.Ia->State == Dhcp6Bound);\r
+ CopyMem (&Private->StationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS));\r
+ \r
+ AsciiPrint ("\n Station IPv6 address is ");\r
+ HttpBootShowIp6Addr (&Private->StationIp.v6);\r
+ AsciiPrint ("\n");\r
+ \r
+ON_EXIT:\r
+ if (EFI_ERROR (Status)) {\r
+ Dhcp6->Stop (Dhcp6);\r
+ Dhcp6->Configure (Dhcp6, NULL);\r
+ } else {\r
+ ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA));\r
+ ZeroMem (&Mode, sizeof (EFI_DHCP6_MODE_DATA));\r
+ Dhcp6->Configure (Dhcp6, &Config);\r
+ }\r
+\r
+ return Status; \r
+ \r
+}\r
+\r
--- /dev/null
+/** @file\r
+ Functions declaration related with DHCPv6 for HTTP boot driver.\r
+\r
+Copyright (c) 2015, 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
+\r
+**/\r
+\r
+\r
+#ifndef __EFI_HTTP_BOOT_DHCP6_H__\r
+#define __EFI_HTTP_BOOT_DHCP6_H__\r
+\r
+#define HTTP_BOOT_OFFER_MAX_NUM 16\r
+#define HTTP_BOOT_DHCP6_OPTION_MAX_NUM 16\r
+#define HTTP_BOOT_DHCP6_OPTION_MAX_SIZE 312\r
+#define HTTP_BOOT_DHCP6_PACKET_MAX_SIZE 1472\r
+#define HTTP_BOOT_IP6_ROUTE_TABLE_TIMEOUT 10\r
+#define HTTP_BOOT_DEFAULT_HOPLIMIT 64\r
+#define HTTP_BOOT_DEFAULT_LIFETIME 50000\r
+\r
+\r
+#define HTTP_BOOT_DHCP6_OPT_CLIENT_ID 1\r
+#define HTTP_BOOT_DHCP6_OPT_SERVER_ID 2\r
+#define HTTP_BOOT_DHCP6_OPT_IA_NA 3\r
+#define HTTP_BOOT_DHCP6_OPT_IA_TA 4\r
+#define HTTP_BOOT_DHCP6_OPT_IAADDR 5\r
+#define HTTP_BOOT_DHCP6_OPT_ORO 6\r
+#define HTTP_BOOT_DHCP6_OPT_PREFERENCE 7\r
+#define HTTP_BOOT_DHCP6_OPT_ELAPSED_TIME 8\r
+#define HTTP_BOOT_DHCP6_OPT_REPLAY_MSG 9\r
+#define HTTP_BOOT_DHCP6_OPT_AUTH 11\r
+#define HTTP_BOOT_DHCP6_OPT_UNICAST 12\r
+#define HTTP_BOOT_DHCP6_OPT_STATUS_CODE 13\r
+#define HTTP_BOOT_DHCP6_OPT_RAPID_COMMIT 14\r
+#define HTTP_BOOT_DHCP6_OPT_USER_CLASS 15\r
+#define HTTP_BOOT_DHCP6_OPT_VENDOR_CLASS 16\r
+#define HTTP_BOOT_DHCP6_OPT_VENDOR_OPTS 17\r
+#define HTTP_BOOT_DHCP6_OPT_INTERFACE_ID 18\r
+#define HTTP_BOOT_DHCP6_OPT_RECONFIG_MSG 19\r
+#define HTTP_BOOT_DHCP6_OPT_RECONFIG_ACCEPT 20\r
+#define HTTP_BOOT_DHCP6_OPT_DNS_SERVERS 23\r
+#define HTTP_BOOT_DHCP6_OPT_BOOT_FILE_URL 59 // Assigned by IANA, RFC 5970\r
+#define HTTP_BOOT_DHCP6_OPT_BOOT_FILE_PARAM 60 // Assigned by IANA, RFC 5970\r
+#define HTTP_BOOT_DHCP6_OPT_ARCH 61 // Assigned by IANA, RFC 5970\r
+#define HTTP_BOOT_DHCP6_OPT_UNDI 62 // Assigned by IANA, RFC 5970\r
+#define HTTP_BOOT_DHCP6_ENTERPRISE_NUM 343 // TODO: IANA TBD: temporarily using Intel's\r
+#define HTTP_BOOT_DHCP6_MAX_BOOT_FILE_SIZE 65535 // It's a limitation of bit length, 65535*512 bytes.\r
+\r
+#define HTTP_BOOT_DHCP6_IDX_IA_NA 0\r
+#define HTTP_BOOT_DHCP6_IDX_BOOT_FILE_URL 1\r
+#define HTTP_BOOT_DHCP6_IDX_BOOT_FILE_PARAM 2\r
+#define HTTP_BOOT_DHCP6_IDX_VENDOR_CLASS 3\r
+#define HTTP_BOOT_DHCP6_IDX_DNS_SERVER 4\r
+#define HTTP_BOOT_DHCP6_IDX_MAX 5\r
+\r
+#pragma pack(1)\r
+typedef struct {\r
+ UINT16 OpCode[256];\r
+} HTTP_BOOT_DHCP6_OPTION_ORO;\r
+\r
+typedef struct {\r
+ UINT8 Type;\r
+ UINT8 MajorVer;\r
+ UINT8 MinorVer;\r
+} HTTP_BOOT_DHCP6_OPTION_UNDI;\r
+\r
+typedef struct {\r
+ UINT16 Type;\r
+} HTTP_BOOT_DHCP6_OPTION_ARCH;\r
+\r
+typedef struct {\r
+ UINT8 ClassIdentifier[10];\r
+ UINT8 ArchitecturePrefix[5];\r
+ UINT8 ArchitectureType[5];\r
+ UINT8 Lit3[1];\r
+ UINT8 InterfaceName[4];\r
+ UINT8 Lit4[1];\r
+ UINT8 UndiMajor[3];\r
+ UINT8 UndiMinor[3];\r
+} HTTP_BOOT_CLASS_ID;\r
+\r
+typedef struct {\r
+ UINT32 Vendor;\r
+ UINT16 ClassLen;\r
+ HTTP_BOOT_CLASS_ID ClassId;\r
+} HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS;\r
+\r
+#pragma pack()\r
+\r
+typedef union {\r
+ HTTP_BOOT_DHCP6_OPTION_ORO *Oro;\r
+ HTTP_BOOT_DHCP6_OPTION_UNDI *Undi;\r
+ HTTP_BOOT_DHCP6_OPTION_ARCH *Arch;\r
+ HTTP_BOOT_DHCP6_OPTION_VENDOR_CLASS *VendorClass;\r
+} HTTP_BOOT_DHCP6_OPTION_ENTRY;\r
+\r
+typedef union {\r
+ EFI_DHCP6_PACKET Offer;\r
+ EFI_DHCP6_PACKET Ack;\r
+ UINT8 Buffer[HTTP_BOOT_DHCP6_PACKET_MAX_SIZE];\r
+} HTTP_BOOT_DHCP6_PACKET;\r
+\r
+typedef struct {\r
+ HTTP_BOOT_DHCP6_PACKET Packet;\r
+ HTTP_BOOT_OFFER_TYPE OfferType;\r
+ EFI_DHCP6_PACKET_OPTION *OptList[HTTP_BOOT_DHCP6_IDX_MAX];\r
+ VOID *UriParser;\r
+} HTTP_BOOT_DHCP6_PACKET_CACHE;\r
+\r
+#define GET_NEXT_DHCP6_OPTION(Opt) \\r
+ (EFI_DHCP6_PACKET_OPTION *) ((UINT8 *) (Opt) + \\r
+ sizeof (EFI_DHCP6_PACKET_OPTION) + (NTOHS ((Opt)->OpLen)) - 1)\r
+\r
+#define GET_DHCP6_OPTION_SIZE(Pkt) \\r
+ ((Pkt)->Length - sizeof (EFI_DHCP6_HEADER))\r
+\r
+/**\r
+ Start the S.A.R.R DHCPv6 process to acquire the IPv6 address and other Http boot information.\r
+\r
+ @param[in] Private Pointer to HTTP_BOOT private data.\r
+\r
+ @retval EFI_SUCCESS The S.A.R.R process successfully finished.\r
+ @retval Others Failed to finish the S.A.R.R process.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootDhcp6Sarr (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ );\r
+\r
+/**\r
+ Set the IP6 policy to Automatic.\r
+\r
+ @param[in] Private The pointer to HTTP_BOOT_PRIVATE_DATA.\r
+\r
+ @retval EFI_SUCCESS Switch the IP policy succesfully.\r
+ @retval Others Unexpect error happened.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Policy (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ );\r
+\r
+/**\r
+ This function will register the default DNS addresses to the network device.\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
+ of EFI_IPv6_ADDRESS instances.\r
+\r
+ @retval EFI_SUCCESS The DNS configuration has been configured successfully.\r
+ @retval Others Failed to configure the address.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Dns (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN UINTN DataLength,\r
+ IN VOID *DnsServerData\r
+ );\r
+\r
+/**\r
+ This function will register the IPv6 gateway address to the network device.\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
+ @retval Others Failed to configure the address.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Gateway (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ );\r
+\r
+/**\r
+ This function will register the station IP address.\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
+ @retval Others Failed to configure the address.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootSetIp6Address (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ );\r
+\r
+#endif\r
NULL\r
};\r
\r
+EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp6DxeDriverBinding = {\r
+ HttpBootIp6DxeDriverBindingSupported,\r
+ HttpBootIp6DxeDriverBindingStart,\r
+ HttpBootIp6DxeDriverBindingStop,\r
+ HTTP_BOOT_DXE_VERSION,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
/**\r
Destroy the HTTP child based on IPv4 stack.\r
\r
\r
if (Private->Dhcp4Child != NULL) {\r
gBS->CloseProtocol (\r
- Private->Dhcp4Child,\r
- &gEfiDhcp4ProtocolGuid,\r
- This->DriverBindingHandle,\r
- Private->Controller\r
- );\r
+ Private->Dhcp4Child,\r
+ &gEfiDhcp4ProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Private->Controller\r
+ );\r
\r
NetLibDestroyServiceChild (\r
Private->Controller,\r
Private->HttpCreated = FALSE;\r
}\r
\r
- gBS->CloseProtocol (\r
- Private->Controller,\r
- &gEfiCallerIdGuid,\r
- This->DriverBindingHandle,\r
- Private->ChildHandle\r
- );\r
+ if (Private->Ip4Nic != NULL) {\r
+ \r
+ gBS->CloseProtocol (\r
+ Private->Controller,\r
+ &gEfiCallerIdGuid,\r
+ This->DriverBindingHandle,\r
+ Private->Ip4Nic->Controller\r
+ );\r
+ \r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Private->Ip4Nic->Controller,\r
+ &gEfiLoadFileProtocolGuid,\r
+ &Private->Ip4Nic->LoadFile,\r
+ &gEfiDevicePathProtocolGuid,\r
+ Private->Ip4Nic->DevicePath,\r
+ NULL\r
+ );\r
+ FreePool (Private->Ip4Nic);\r
+ Private->Ip4Nic = NULL;\r
+ }\r
+\r
+}\r
+\r
+/**\r
+ Destroy the HTTP child based on IPv6 stack.\r
+\r
+ @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.\r
+ @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.\r
+\r
+**/\r
+VOID\r
+HttpBootDestroyIp6Children (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ ASSERT (This != NULL);\r
+ ASSERT (Private != NULL);\r
+ ASSERT (Private->UsingIpv6 == TRUE);\r
+ \r
+ if (Private->Ip6Child != NULL) {\r
+ gBS->CloseProtocol (\r
+ Private->Ip6Child,\r
+ &gEfiIp6ProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Private->Controller\r
+ );\r
+\r
+ NetLibDestroyServiceChild (\r
+ Private->Controller,\r
+ This->DriverBindingHandle,\r
+ &gEfiIp6ServiceBindingProtocolGuid,\r
+ Private->Ip6Child\r
+ );\r
+ }\r
+\r
+ if (Private->Dhcp6Child != NULL) {\r
+ gBS->CloseProtocol (\r
+ Private->Dhcp6Child,\r
+ &gEfiDhcp6ProtocolGuid,\r
+ This->DriverBindingHandle,\r
+ Private->Controller\r
+ );\r
\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- Private->ChildHandle,\r
- &gEfiLoadFileProtocolGuid,\r
- &Private->LoadFile,\r
- &gEfiDevicePathProtocolGuid,\r
- Private->DevicePath,\r
- NULL\r
- );\r
+ NetLibDestroyServiceChild (\r
+ Private->Controller,\r
+ This->DriverBindingHandle,\r
+ &gEfiDhcp6ServiceBindingProtocolGuid,\r
+ Private->Dhcp6Child\r
+ );\r
+ }\r
\r
- if (Private->DevicePath != NULL) {\r
- FreePool (Private->DevicePath);\r
- Private->DevicePath = NULL;\r
+ if (Private->HttpCreated) {\r
+ HttpIoDestroyIo(&Private->HttpIo);\r
+ Private->HttpCreated = FALSE;\r
+ }\r
+ \r
+ if (Private->Ip6Nic != NULL) {\r
+ \r
+ gBS->CloseProtocol (\r
+ Private->Controller,\r
+ &gEfiCallerIdGuid,\r
+ This->DriverBindingHandle,\r
+ Private->Ip6Nic->Controller\r
+ );\r
+ \r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Private->Ip6Nic->Controller,\r
+ &gEfiLoadFileProtocolGuid,\r
+ &Private->Ip6Nic->LoadFile,\r
+ &gEfiDevicePathProtocolGuid,\r
+ Private->Ip6Nic->DevicePath,\r
+ NULL\r
+ );\r
+ FreePool (Private->Ip6Nic);\r
+ Private->Ip6Nic = NULL;\r
}\r
}\r
\r
// Try to open the DHCP4, HTTP4 and Device Path protocol.\r
//\r
Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiDhcp4ServiceBindingProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
+ ControllerHandle,\r
+ &gEfiDhcp4ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
+ ControllerHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
+ ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
\r
return Status;\r
}\r
ControllerHandle,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
+\r
if (!EFI_ERROR (Status)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
+ Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);\r
+ } else {\r
+ //\r
+ // Initialize the private data structure.\r
+ //\r
+ Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));\r
+ if (Private == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;\r
+ Private->Controller = ControllerHandle;\r
+ Private->Image = This->ImageHandle;\r
+ InitializeListHead (&Private->CacheList);\r
+ //\r
+ // Get the NII interface if it exists, it's not required.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
+ (VOID **) &Private->Nii,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Private->Nii = NULL;\r
+ }\r
\r
- //\r
- // Initialize the private data structure.\r
- //\r
- Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));\r
- if (Private == NULL) {\r
+ //\r
+ // Open Device Path Protocol to prepare for appending IP and URI node.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &Private->ParentDevicePath,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between\r
+ // NIC handle and the private data.\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &ControllerHandle,\r
+ &gEfiCallerIdGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &Private->Id\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ }\r
+ \r
+ if (Private->Ip4Nic != NULL) {\r
+ //\r
+ // Already created before\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ Private->Ip4Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));\r
+ if (Private->Ip4Nic == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;\r
- Private->Controller = ControllerHandle;\r
- Private->Image = This->ImageHandle;\r
- Private->UsingIpv6 = FALSE;\r
- InitializeListHead (&Private->CacheList);\r
-\r
+ Private->Ip4Nic->Private = Private;\r
+ Private->Ip4Nic->Signature = HTTP_BOOT_VIRTUAL_NIC_SIGNATURE;\r
+ \r
//\r
- // Create DHCP child instance.\r
+ // Create DHCP4 child instance.\r
//\r
Status = NetLibCreateServiceChild (\r
ControllerHandle,\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
-\r
+ \r
Status = gBS->OpenProtocol (\r
Private->Dhcp4Child,\r
&gEfiDhcp4ProtocolGuid,\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
-\r
+ \r
//\r
// Get the Ip4Config2 protocol, it's required to configure the default gateway address.\r
//\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
-\r
- //\r
- // Get the NII interface if it exists, it's not required.\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
- (VOID **) &Private->Nii,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- Private->Nii = NULL;\r
- }\r
-\r
- //\r
- // Open Device Path Protocol to prepare for appending IP and URI node.\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiDevicePathProtocolGuid,\r
- (VOID **) &Private->ParentDevicePath,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
+ \r
//\r
// Append IPv4 device path node.\r
//\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_ERROR;\r
}\r
-\r
+ \r
//\r
// Append URI device path node.\r
//\r
Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
Node->DevPath.SubType = MSG_URI_DP;\r
SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
- Private->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
+ Private->Ip4Nic->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
FreePool (Node);\r
FreePool (DevicePath);\r
- if (Private->DevicePath == NULL) {\r
+ if (Private->Ip4Nic->DevicePath == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_ERROR;\r
}\r
-\r
+ \r
//\r
// Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.\r
//\r
- CopyMem (&Private->LoadFile, &gHttpBootDxeLoadFile, sizeof (Private->LoadFile));\r
+ CopyMem (&Private->Ip4Nic->LoadFile, &gHttpBootDxeLoadFile, sizeof (EFI_LOAD_FILE_PROTOCOL));\r
Status = gBS->InstallMultipleProtocolInterfaces (\r
- &Private->ChildHandle,\r
+ &Private->Ip4Nic->Controller,\r
&gEfiLoadFileProtocolGuid,\r
- &Private->LoadFile,\r
+ &Private->Ip4Nic->LoadFile,\r
&gEfiDevicePathProtocolGuid,\r
- Private->DevicePath,\r
+ Private->Ip4Nic->DevicePath,\r
NULL\r
);\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
-\r
- //\r
- // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between\r
- // NIC handle and the private data.\r
- //\r
- Status = gBS->InstallProtocolInterface (\r
- &ControllerHandle,\r
- &gEfiCallerIdGuid,\r
- EFI_NATIVE_INTERFACE,\r
- &Private->Id\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
+ \r
//\r
// Open the Caller Id child to setup a parent-child relationship between\r
- // real NIC handle and the HTTP boot child handle.\r
+ // real NIC handle and the HTTP boot Ipv4 NIC handle.\r
//\r
Status = gBS->OpenProtocol (\r
ControllerHandle,\r
&gEfiCallerIdGuid,\r
(VOID **) &Id,\r
This->DriverBindingHandle,\r
- Private->ChildHandle,\r
+ Private->Ip4Nic->Controller,\r
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
);\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
-\r
+ \r
return EFI_SUCCESS;\r
\r
+ \r
ON_ERROR:\r
\r
HttpBootDestroyIp4Children (This, Private);\r
return Status;\r
}\r
\r
+\r
/**\r
Stops a device controller or a bus controller.\r
\r
// Destory all child instance and uninstall protocol interface.\r
//\r
HttpBootDestroyIp4Children (This, Private);\r
+ \r
+ if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
+ //\r
+ // Release the cached data.\r
+ //\r
+ HttpBootFreeCacheList (Private);\r
+ \r
+ gBS->UninstallProtocolInterface (\r
+ NicHandle,\r
+ &gEfiCallerIdGuid,\r
+ &Private->Id\r
+ );\r
+ FreePool (Private);\r
\r
- //\r
- // Release the cached data.\r
- //\r
- HttpBootFreeCacheList (Private);\r
-\r
- gBS->UninstallProtocolInterface (\r
- NicHandle,\r
- &gEfiCallerIdGuid,\r
- &Private->Id\r
- );\r
- FreePool (Private);\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- This is the declaration of an EFI image entry point. This entry point is\r
- the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
- both device drivers and bus drivers.\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
\r
- @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
- @param[in] SystemTable A pointer to the EFI System Table.\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
\r
- @retval EFI_SUCCESS The operation completed successfully.\r
- @retval Others An unexpected error occurred.\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HttpBootDxeDriverEntryPoint (\r
- IN EFI_HANDLE ImageHandle,\r
- IN EFI_SYSTEM_TABLE *SystemTable\r
+HttpBootIp6DxeDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
)\r
{\r
+ EFI_STATUS Status;\r
+ \r
//\r
- // Install UEFI Driver Model protocol(s).\r
+ // Try to open the DHCP6, HTTP and Device Path protocol.\r
//\r
- return EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gHttpBootIp4DxeDriverBinding,\r
- ImageHandle,\r
- &gHttpBootDxeComponentName,\r
- &gHttpBootDxeComponentName2\r
- );\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiDhcp6ServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ return Status;\r
+\r
+}\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootIp6DxeDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HTTP_BOOT_PRIVATE_DATA *Private;\r
+ EFI_DEV_PATH *Node;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ UINT32 *Id;\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **) &Id,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ \r
+ if (!EFI_ERROR (Status)) {\r
+ Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);\r
+ } else {\r
+ //\r
+ // Initialize the private data structure.\r
+ //\r
+ Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));\r
+ if (Private == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;\r
+ Private->Controller = ControllerHandle;\r
+ Private->Image = This->ImageHandle;\r
+ InitializeListHead (&Private->CacheList);\r
+ //\r
+ // Get the NII interface if it exists, it's not required.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
+ (VOID **) &Private->Nii,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Private->Nii = NULL;\r
+ }\r
+\r
+ //\r
+ // Open Device Path Protocol to prepare for appending IP and URI node.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ (VOID **) &Private->ParentDevicePath,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between\r
+ // NIC handle and the private data.\r
+ //\r
+ Status = gBS->InstallProtocolInterface (\r
+ &ControllerHandle,\r
+ &gEfiCallerIdGuid,\r
+ EFI_NATIVE_INTERFACE,\r
+ &Private->Id\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ }\r
+ \r
+ if (Private->Ip6Nic != NULL) {\r
+ //\r
+ // Already created before\r
+ //\r
+ return EFI_SUCCESS;\r
+ }\r
+ \r
+ Private->Ip6Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));\r
+ if (Private->Ip6Nic == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Private->Ip6Nic->Private = Private;\r
+ Private->Ip6Nic->Signature = HTTP_BOOT_VIRTUAL_NIC_SIGNATURE;\r
+\r
+ //\r
+ // Create Dhcp6 child and open Dhcp6 protocol\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ This->DriverBindingHandle,\r
+ &gEfiDhcp6ServiceBindingProtocolGuid,\r
+ &Private->Dhcp6Child\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Private->Dhcp6Child,\r
+ &gEfiDhcp6ProtocolGuid,\r
+ (VOID **) &Private->Dhcp6,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Create Ip6 child and open Ip6 protocol for background ICMP packets.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ This->DriverBindingHandle,\r
+ &gEfiIp6ServiceBindingProtocolGuid,\r
+ &Private->Ip6Child\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ Private->Ip6Child,\r
+ &gEfiIp6ProtocolGuid,\r
+ (VOID **) &Private->Ip6,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Locate Ip6Config protocol, it's required to configure the default gateway address.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiIp6ConfigProtocolGuid,\r
+ (VOID **) &Private->Ip6Config,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Append IPv6 device path node.\r
+ //\r
+ Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));\r
+ if (Node == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_ERROR;\r
+ }\r
+ Node->Ipv6.Header.Type = MESSAGING_DEVICE_PATH;\r
+ Node->Ipv6.Header.SubType = MSG_IPv6_DP;\r
+ Node->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;\r
+ SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH));\r
+ DevicePath = AppendDevicePathNode(Private->ParentDevicePath, (EFI_DEVICE_PATH*) Node);\r
+ FreePool(Node);\r
+ if (DevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Append URI device path node.\r
+ //\r
+ Node = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
+ if (Node == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_ERROR;\r
+ }\r
+ Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
+ Node->DevPath.SubType = MSG_URI_DP;\r
+ SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
+ Private->Ip6Nic->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
+ FreePool (Node);\r
+ FreePool (DevicePath);\r
+ if (Private->Ip6Nic->DevicePath == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.\r
+ //\r
+ CopyMem (&Private->Ip6Nic->LoadFile, &gHttpBootDxeLoadFile, sizeof (Private->LoadFile));\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &Private->Ip6Nic->Controller,\r
+ &gEfiLoadFileProtocolGuid,\r
+ &Private->Ip6Nic->LoadFile,\r
+ &gEfiDevicePathProtocolGuid,\r
+ Private->Ip6Nic->DevicePath,\r
+ NULL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ //\r
+ // Open the Caller Id child to setup a parent-child relationship between\r
+ // real NIC handle and the HTTP boot child handle.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **) &Id,\r
+ This->DriverBindingHandle,\r
+ Private->Ip6Nic->Controller,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ \r
+ON_ERROR:\r
+ \r
+ HttpBootDestroyIp6Children(This, Private);\r
+ FreePool (Private);\r
+\r
+ return Status;\r
+ \r
+}\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootIp6DxeDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
+ HTTP_BOOT_PRIVATE_DATA *Private;\r
+ EFI_HANDLE NicHandle;\r
+ UINT32 *Id;\r
+\r
+ //\r
+ // Try to get the Load File Protocol from the controller handle.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiLoadFileProtocolGuid,\r
+ (VOID **) &LoadFile,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // If failed, try to find the NIC handle for this controller.\r
+ //\r
+ NicHandle = HttpBootGetNicByIp6Children (ControllerHandle);\r
+ if (NicHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ //\r
+ // Try to retrieve the private data by the Caller Id Guid.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ NicHandle,\r
+ &gEfiCallerIdGuid,\r
+ (VOID **) &Id,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id);\r
+ } else {\r
+ Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile);\r
+ NicHandle = Private->Controller;\r
+ }\r
+\r
+ //\r
+ // Disable the HTTP boot function.\r
+ //\r
+ Status = HttpBootStop (Private);\r
+ if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Destory all child instance and uninstall protocol interface.\r
+ //\r
+ HttpBootDestroyIp6Children (This, Private);\r
+\r
+ if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
+ //\r
+ // Release the cached data.\r
+ //\r
+ HttpBootFreeCacheList (Private);\r
+ \r
+ gBS->UninstallProtocolInterface (\r
+ NicHandle,\r
+ &gEfiCallerIdGuid,\r
+ &Private->Id\r
+ );\r
+ FreePool (Private);\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+/**\r
+ This is the declaration of an EFI image entry point. This entry point is\r
+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
+ both device drivers and bus drivers.\r
+\r
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
+ @param[in] SystemTable A pointer to the EFI System Table.\r
+\r
+ @retval EFI_SUCCESS The operation completed successfully.\r
+ @retval Others An unexpected error occurred.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootDxeDriverEntryPoint (\r
+ IN EFI_HANDLE ImageHandle,\r
+ IN EFI_SYSTEM_TABLE *SystemTable\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ //\r
+ // Install UEFI Driver Model protocol(s).\r
+ //\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gHttpBootIp4DxeDriverBinding,\r
+ ImageHandle,\r
+ &gHttpBootDxeComponentName,\r
+ &gHttpBootDxeComponentName2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gHttpBootIp6DxeDriverBinding,\r
+ NULL,\r
+ &gHttpBootDxeComponentName,\r
+ &gHttpBootDxeComponentName2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces(\r
+ ImageHandle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ &gHttpBootIp4DxeDriverBinding,\r
+ &gEfiComponentName2ProtocolGuid,\r
+ &gHttpBootDxeComponentName2,\r
+ &gEfiComponentNameProtocolGuid,\r
+ &gHttpBootDxeComponentName,\r
+ NULL\r
+ );\r
+ }\r
+ return Status;\r
}\r
\r
//\r
#include <Protocol/NetworkInterfaceIdentifier.h>\r
#include <Protocol/Dhcp4.h>\r
+#include <Protocol/Dhcp6.h>\r
+#include <Protocol/Dns6.h>\r
#include <Protocol/Http.h>\r
#include <Protocol/Ip4Config2.h>\r
-\r
+#include <Protocol/Ip6Config.h>\r
//\r
// Produced Protocols\r
//\r
// Private data structure\r
//\r
typedef struct _HTTP_BOOT_PRIVATE_DATA HTTP_BOOT_PRIVATE_DATA;\r
+typedef struct _HTTP_BOOT_VIRTUAL_NIC HTTP_BOOT_VIRTUAL_NIC;\r
\r
//\r
// Include files with internal function prototypes\r
//\r
#include "HttpBootComponentName.h"\r
#include "HttpBootDhcp4.h"\r
+#include "HttpBootDhcp6.h"\r
#include "HttpBootImpl.h"\r
#include "HttpBootSupport.h"\r
#include "HttpBootClient.h"\r
\r
typedef union {\r
HTTP_BOOT_DHCP4_PACKET_CACHE Dhcp4;\r
+ HTTP_BOOT_DHCP6_PACKET_CACHE Dhcp6;\r
} HTTP_BOOT_DHCP_PACKET_CACHE;\r
\r
+struct _HTTP_BOOT_VIRTUAL_NIC {\r
+ UINT32 Signature;\r
+ EFI_HANDLE Controller;\r
+ EFI_LOAD_FILE_PROTOCOL LoadFile;\r
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
+ HTTP_BOOT_PRIVATE_DATA *Private;\r
+};\r
+\r
struct _HTTP_BOOT_PRIVATE_DATA {\r
UINT32 Signature;\r
EFI_HANDLE Controller;\r
EFI_HANDLE Image;\r
\r
+ HTTP_BOOT_VIRTUAL_NIC *Ip4Nic;\r
+ HTTP_BOOT_VIRTUAL_NIC *Ip6Nic;\r
+\r
//\r
// Cousumed children\r
//\r
+ EFI_HANDLE Ip6Child;\r
EFI_HANDLE Dhcp4Child;\r
+ EFI_HANDLE Dhcp6Child;\r
HTTP_IO HttpIo;\r
BOOLEAN HttpCreated;\r
\r
// Consumed protocol\r
//\r
EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;\r
+ EFI_IP6_PROTOCOL *Ip6;\r
EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2;\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
EFI_DHCP4_PROTOCOL *Dhcp4;\r
+ EFI_DHCP6_PROTOCOL *Dhcp6;\r
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;\r
\r
- //\r
- // Produced children\r
- //\r
- EFI_HANDLE ChildHandle;\r
\r
//\r
// Produced protocol\r
EFI_IP_ADDRESS StationIp;\r
EFI_IP_ADDRESS SubnetMask;\r
EFI_IP_ADDRESS GatewayIp;\r
+ EFI_IP_ADDRESS ServerIp;\r
UINT16 Port;\r
CHAR8 *BootFileUri;\r
VOID *BootFileUriParser;\r
UINTN BootFileSize;\r
+ BOOLEAN NoGateway;\r
\r
//\r
// Cached HTTP data\r
};\r
\r
#define HTTP_BOOT_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('H', 'B', 'P', 'D')\r
+#define HTTP_BOOT_VIRTUAL_NIC_SIGNATURE SIGNATURE_32 ('H', 'B', 'V', 'N')\r
#define HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE(a) CR (a, HTTP_BOOT_PRIVATE_DATA, LoadFile, HTTP_BOOT_PRIVATE_DATA_SIGNATURE)\r
#define HTTP_BOOT_PRIVATE_DATA_FROM_ID(a) CR (a, HTTP_BOOT_PRIVATE_DATA, Id, HTTP_BOOT_PRIVATE_DATA_SIGNATURE)\r
-\r
+#define HTTP_BOOT_VIRTUAL_NIC_FROM_LOADFILE(a) CR (a, HTTP_BOOT_VIRTUAL_NIC, LoadFile, HTTP_BOOT_VIRTUAL_NIC_SIGNATURE)\r
extern EFI_LOAD_FILE_PROTOCOL gHttpBootDxeLoadFile;\r
\r
/**\r
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
);\r
\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootIp6DxeDriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootIp6DxeDriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootIp6DxeDriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ );\r
#endif\r
HttpBootImpl.c\r
HttpBootDhcp4.h\r
HttpBootDhcp4.c\r
+ HttpBootDhcp6.h\r
+ HttpBootDhcp6.c\r
HttpBootSupport.h\r
HttpBootSupport.c\r
HttpBootClient.h\r
gEfiDhcp4ServiceBindingProtocolGuid ## TO_START\r
gEfiDhcp4ProtocolGuid ## TO_START\r
gEfiIp4Config2ProtocolGuid ## TO_START\r
+ gEfiDhcp6ServiceBindingProtocolGuid ## TO_START\r
+ gEfiDhcp6ProtocolGuid ## TO_START\r
+ gEfiDns6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiDns6ProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiIp6ServiceBindingProtocolGuid ## TO_START\r
+ gEfiIp6ProtocolGuid ## TO_START\r
+ gEfiIp6ConfigProtocolGuid ## TO_START\r
gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## SOMETIMES_CONSUMES\r
\r
[UserExtensions.TianoCore."ExtraFiles"]\r
Enable the use of UEFI HTTP boot function.\r
\r
@param[in] Private The pointer to the driver's private data.\r
+ @param[in] UsingIpv6 Specifies the type of IP addresses that are to be\r
+ used during the session that is being started.\r
+ Set to TRUE for IPv6, and FALSE for IPv4.\r
\r
@retval EFI_SUCCESS HTTP boot was successfully enabled.\r
@retval EFI_INVALID_PARAMETER Private is NULL.\r
**/\r
EFI_STATUS\r
HttpBootStart (\r
- IN HTTP_BOOT_PRIVATE_DATA *Private\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN BOOLEAN UsingIpv6\r
)\r
{\r
- UINTN Index;\r
+ UINTN Index;\r
+ EFI_STATUS Status;\r
\r
if (Private == NULL) {\r
return EFI_INVALID_PARAMETER;\r
return EFI_ALREADY_STARTED;\r
}\r
\r
+ //\r
+ // Detect whether using ipv6 or not, and set it to the private data.\r
+ //\r
+ if (UsingIpv6 && Private->Ip6Nic != NULL) {\r
+ Private->UsingIpv6 = TRUE;\r
+ } else if (!UsingIpv6 && Private->Ip4Nic != NULL) {\r
+ Private->UsingIpv6 = FALSE;\r
+ } else {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+ \r
+ //\r
+ // Init the content of cached DHCP offer list.\r
+ //\r
+ ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));\r
if (!Private->UsingIpv6) {\r
- //\r
- // Init the content of cached DHCP offer list.\r
- //\r
- ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));\r
for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {\r
Private->OfferBuffer[Index].Dhcp4.Packet.Offer.Size = HTTP_BOOT_DHCP4_PACKET_MAX_SIZE;\r
}\r
} else {\r
- ASSERT (FALSE);\r
+ for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {\r
+ Private->OfferBuffer[Index].Dhcp6.Packet.Offer.Size = HTTP_BOOT_DHCP6_PACKET_MAX_SIZE;\r
+ }\r
}\r
\r
+ if (Private->UsingIpv6) {\r
+ //\r
+ // Set Ip6 policy to Automatic to start the Ip6 router discovery.\r
+ //\r
+ Status = HttpBootSetIp6Policy (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
Private->Started = TRUE;\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information.\r
+ Attempt to complete a DHCPv4 D.O.R.A or DHCPv6 S.R.A.A sequence to retrieve the boot resource information.\r
\r
@param[in] Private The pointer to the driver's private data.\r
\r
Status = EFI_DEVICE_ERROR;\r
\r
if (!Private->UsingIpv6) {\r
+ //\r
+ // Start D.O.R.A process to get a IPv4 address and other boot information.\r
+ //\r
Status = HttpBootDhcp4Dora (Private);\r
} else {\r
- ASSERT (FALSE);\r
+ //\r
+ // Start S.A.R.R process to get a IPv6 address and other boot information.\r
+ //\r
+ Status = HttpBootDhcp6Sarr (Private);\r
}\r
\r
return Status;\r
Private->BootFileUriParser = NULL;\r
Private->BootFileSize = 0;\r
Private->SelectIndex = 0;\r
- Private->SelectProxyType = HttpOfferTypeMax;\r
+ Private->SelectProxyType = HttpOfferTypeMax; \r
\r
if (!Private->UsingIpv6) {\r
//\r
}\r
}\r
} else {\r
- ASSERT (FALSE);\r
+ //\r
+ // Stop and release the DHCP6 child.\r
+ //\r
+ Private->Dhcp6->Stop (Private->Dhcp6);\r
+ Private->Dhcp6->Configure (Private->Dhcp6, NULL);\r
+ \r
+ for (Index = 0; Index < HTTP_BOOT_OFFER_MAX_NUM; Index++) {\r
+ if (Private->OfferBuffer[Index].Dhcp6.UriParser) {\r
+ HttpUrlFreeParser (Private->OfferBuffer[Index].Dhcp6.UriParser);\r
+ }\r
+ }\r
}\r
\r
ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));\r
)\r
{\r
HTTP_BOOT_PRIVATE_DATA *Private;\r
+ HTTP_BOOT_VIRTUAL_NIC *VirtualNic;\r
BOOLEAN MediaPresent;\r
+ BOOLEAN UsingIpv6;\r
EFI_STATUS Status;\r
\r
if (This == NULL || BufferSize == NULL) {\r
return EFI_UNSUPPORTED;\r
}\r
\r
- Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (This);\r
-\r
+ VirtualNic = HTTP_BOOT_VIRTUAL_NIC_FROM_LOADFILE (This);\r
+ Private = VirtualNic->Private;\r
+ UsingIpv6 = FALSE;\r
+ \r
//\r
// Check media status before HTTP boot start\r
//\r
return EFI_NO_MEDIA;\r
}\r
\r
+ //\r
+ // Check whether the virtual nic is using IPv6 or not.\r
+ //\r
+ if (VirtualNic == Private->Ip6Nic) {\r
+ UsingIpv6 = TRUE;\r
+ }\r
+ \r
//\r
// Initialize HTTP boot and load the boot file.\r
//\r
- Status = HttpBootStart (Private);\r
+ Status = HttpBootStart (Private, UsingIpv6);\r
+ if (Status == EFI_ALREADY_STARTED && UsingIpv6 != Private->UsingIpv6) {\r
+ //\r
+ // Http boot Driver has already been started but not on the required IP version, restart it.\r
+ //\r
+ Status = HttpBootStop (Private);\r
+ if (!EFI_ERROR (Status)) {\r
+ Status = HttpBootStart (Private, UsingIpv6);\r
+ }\r
+ }\r
if (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED) {\r
Status = HttpBootLoadFile (Private, BufferSize, Buffer);\r
}\r
if (Status != EFI_SUCCESS && Status != EFI_BUFFER_TOO_SMALL) {\r
HttpBootStop (Private);\r
} else {\r
- //\r
- // Stop and release the DHCP4 child.\r
- //\r
- Private->Dhcp4->Stop (Private->Dhcp4);\r
- Private->Dhcp4->Configure (Private->Dhcp4, NULL);\r
+ if (!Private->UsingIpv6) {\r
+ //\r
+ // Stop and release the DHCP4 child.\r
+ //\r
+ Private->Dhcp4->Stop (Private->Dhcp4);\r
+ Private->Dhcp4->Configure (Private->Dhcp4, NULL);\r
+ } else {\r
+ //\r
+ // Stop and release the DHCP6 child.\r
+ //\r
+ Private->Dhcp6->Stop (Private->Dhcp6);\r
+ Private->Dhcp6->Configure (Private->Dhcp6, NULL);\r
+ }\r
}\r
\r
return Status;\r
#define __EFI_HTTP_BOOT_IMPL_H__\r
\r
/**\r
- Attempt to complete a DHCPv4 D.O.R.A sequence to retrieve the boot resource information.\r
+ Attempt to complete a DHCPv4 D.O.R.A or DHCPv6 S.R.A.A sequence to retrieve the boot resource information.\r
\r
@param[in] Private The pointer to the driver's private data.\r
\r
return NicHandle;\r
}\r
\r
+/**\r
+ Get the Nic handle using any child handle in the IPv6 stack.\r
+\r
+ @param[in] ControllerHandle Pointer to child handle over IPv6.\r
+\r
+ @return NicHandle The pointer to the Nic handle.\r
+ @return NULL Can't find the Nic handle.\r
+\r
+**/\r
+EFI_HANDLE\r
+HttpBootGetNicByIp6Children (\r
+ IN EFI_HANDLE ControllerHandle\r
+ )\r
+{\r
+ EFI_HANDLE NicHandle;\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiHttpProtocolGuid);\r
+ if (NicHandle == NULL) {\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
+ if (NicHandle == NULL) {\r
+ return NULL;\r
+ }\r
+ }\r
+\r
+ return NicHandle;\r
+}\r
\r
/**\r
This function is to convert UINTN to ASCII string with the required formatting.\r
}\r
}\r
\r
+/**\r
+ This function is to display the IPv6 address.\r
+\r
+ @param[in] Ip The pointer to the IPv6 address.\r
+\r
+**/\r
+VOID\r
+HttpBootShowIp6Addr (\r
+ IN EFI_IPv6_ADDRESS *Ip\r
+ )\r
+{\r
+ UINTN Index;\r
+\r
+ for (Index = 0; Index < 16; Index++) {\r
+\r
+ if (Ip->Addr[Index] != 0) {\r
+ AsciiPrint ("%x", Ip->Addr[Index]);\r
+ }\r
+ Index++;\r
+ if (Index > 15) {\r
+ return;\r
+ }\r
+ if (((Ip->Addr[Index] & 0xf0) == 0) && (Ip->Addr[Index - 1] != 0)) {\r
+ AsciiPrint ("0");\r
+ }\r
+ AsciiPrint ("%x", Ip->Addr[Index]);\r
+ if (Index < 15) {\r
+ AsciiPrint (":");\r
+ }\r
+ }\r
+}\r
+\r
+/**\r
+ Notify the callback function when an event is triggered.\r
+\r
+ @param[in] Event The triggered event.\r
+ @param[in] Context The opaque parameter to the function.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HttpBootCommonNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ *((BOOLEAN *) Context) = TRUE;\r
+}\r
+\r
+/**\r
+ Retrieve the host address using the EFI_DNS6_PROTOCOL.\r
+\r
+ @param[in] Private The pointer to the driver's private data.\r
+ @param[in] HostName Pointer to buffer containing hostname.\r
+ @param[out] IpAddress On output, pointer to buffer containing IPv6 address.\r
+\r
+ @retval EFI_SUCCESS Operation succeeded.\r
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
+ @retval Others Other errors as indicated. \r
+**/\r
+EFI_STATUS\r
+HttpBootDns (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN CHAR16 *HostName,\r
+ OUT EFI_IPv6_ADDRESS *IpAddress \r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_DNS6_PROTOCOL *Dns6;\r
+ EFI_DNS6_CONFIG_DATA Dns6ConfigData;\r
+ EFI_DNS6_COMPLETION_TOKEN Token;\r
+ EFI_HANDLE Dns6Handle;\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
+ EFI_IPv6_ADDRESS *DnsServerList;\r
+ UINTN DnsServerListCount;\r
+ UINTN DataSize;\r
+ BOOLEAN IsDone; \r
+ \r
+ DnsServerList = NULL;\r
+ DnsServerListCount = 0;\r
+ Dns6 = NULL;\r
+ Dns6Handle = NULL;\r
+ ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));\r
+ \r
+ //\r
+ // Get DNS server list from EFI IPv6 Configuration protocol.\r
+ //\r
+ Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Get the required size.\r
+ //\r
+ DataSize = 0;\r
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ DnsServerList = AllocatePool (DataSize);\r
+ if (DnsServerList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ } \r
+\r
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (DnsServerList);\r
+ DnsServerList = NULL;\r
+ } else {\r
+ DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
+ }\r
+ }\r
+ }\r
+ //\r
+ // Create a DNSv6 child instance and get the protocol.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ Private->Controller,\r
+ Private->Image,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ &Dns6Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ } \r
+ \r
+ Status = gBS->OpenProtocol (\r
+ Dns6Handle,\r
+ &gEfiDns6ProtocolGuid,\r
+ (VOID **) &Dns6,\r
+ Private->Image,\r
+ Private->Controller,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Configure DNS6 instance for the DNS server address and protocol.\r
+ //\r
+ ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));\r
+ Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;\r
+ Dns6ConfigData.DnsServerList = DnsServerList;\r
+ Dns6ConfigData.EnableDnsCache = TRUE;\r
+ Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;\r
+ IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6);\r
+ Status = Dns6->Configure (\r
+ Dns6,\r
+ &Dns6ConfigData\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+ \r
+ Token.Status = EFI_NOT_READY;\r
+ IsDone = FALSE;\r
+ //\r
+ // Create event to set the IsDone flag when name resolution is finished.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpBootCommonNotify,\r
+ &IsDone,\r
+ &Token.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Start asynchronous name resolution.\r
+ //\r
+ Status = Dns6->HostNameToIp (Dns6, HostName, &Token);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ while (!IsDone) {\r
+ Dns6->Poll (Dns6);\r
+ }\r
+ \r
+ //\r
+ // Name resolution is done, check result.\r
+ //\r
+ Status = Token.Status; \r
+ if (!EFI_ERROR (Status)) {\r
+ if (Token.RspData.H2AData == NULL) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ //\r
+ // We just return the first IPv6 address from DNS protocol.\r
+ //\r
+ IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
+ Status = EFI_SUCCESS;\r
+ }\r
+Exit:\r
+\r
+ if (Token.Event != NULL) {\r
+ gBS->CloseEvent (Token.Event);\r
+ }\r
+ if (Token.RspData.H2AData != NULL) {\r
+ if (Token.RspData.H2AData->IpList != NULL) {\r
+ FreePool (Token.RspData.H2AData->IpList);\r
+ }\r
+ FreePool (Token.RspData.H2AData);\r
+ }\r
+\r
+ if (Dns6 != NULL) {\r
+ Dns6->Configure (Dns6, NULL);\r
+ \r
+ gBS->CloseProtocol (\r
+ Dns6Handle,\r
+ &gEfiDns6ProtocolGuid,\r
+ Private->Image,\r
+ Private->Controller\r
+ );\r
+ }\r
+\r
+ if (Dns6Handle != NULL) {\r
+ NetLibDestroyServiceChild (\r
+ Private->Controller,\r
+ Private->Image,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ Dns6Handle\r
+ );\r
+ }\r
+\r
+ if (DnsServerList != NULL) {\r
+ FreePool (DnsServerList);\r
+ }\r
+ \r
+ return Status; \r
+}\r
/**\r
Create a HTTP_IO_HEADER to hold the HTTP header items.\r
\r
HTTP_IO_HEADER *\r
HttpBootCreateHeader (\r
UINTN MaxHeaderCount\r
-)\r
+ )\r
{\r
HTTP_IO_HEADER *HttpIoHeader;\r
\r
return EFI_SUCCESS;\r
}\r
\r
-/**\r
- Notify the callback function when an event is triggered.\r
-\r
- @param[in] Event The triggered event.\r
- @param[in] Context The opaque parameter to the function.\r
-\r
-**/\r
-VOID\r
-EFIAPI\r
-HttpIoCommonNotify (\r
- IN EFI_EVENT Event,\r
- IN VOID *Context\r
- )\r
-{\r
- *((BOOLEAN *) Context) = TRUE;\r
-}\r
-\r
/**\r
Create a HTTP_IO to access the HTTP service. It will create and configure\r
a HTTP child handle.\r
EFI_STATUS Status;\r
EFI_HTTP_CONFIG_DATA HttpConfigData;\r
EFI_HTTPv4_ACCESS_POINT Http4AccessPoint;\r
+ EFI_HTTPv6_ACCESS_POINT Http6AccessPoint;\r
EFI_HTTP_PROTOCOL *Http;\r
EFI_EVENT Event;\r
\r
IP4_COPY_ADDRESS (&Http4AccessPoint.LocalSubnet, &ConfigData->Config4.SubnetMask);\r
HttpConfigData.AccessPoint.IPv4Node = &Http4AccessPoint; \r
} else {\r
- ASSERT (FALSE);\r
+ HttpConfigData.LocalAddressIsIPv6 = TRUE;\r
+ Http6AccessPoint.LocalPort = ConfigData->Config6.LocalPort;\r
+ IP6_COPY_ADDRESS (&Http6AccessPoint.LocalAddress, &ConfigData->Config6.LocalIp);\r
+ HttpConfigData.AccessPoint.IPv6Node = &Http6AccessPoint;\r
}\r
\r
Status = Http->Configure (Http, &HttpConfigData);\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
- HttpIoCommonNotify,\r
+ HttpBootCommonNotify,\r
&HttpIo->IsTxDone,\r
&Event\r
);\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
- HttpIoCommonNotify,\r
+ HttpBootCommonNotify,\r
&HttpIo->IsRxDone,\r
&Event\r
);\r
//\r
// Store the received data into the wrapper.\r
//\r
- Status = HttpIo->ReqToken.Status;\r
+ Status = HttpIo->RspToken.Status;\r
if (!EFI_ERROR (Status)) {\r
ResponseData->HeaderCount = HttpIo->RspToken.Message->HeaderCount;\r
ResponseData->Headers = HttpIo->RspToken.Message->Headers;\r
IN EFI_HANDLE ControllerHandle\r
);\r
\r
+/**\r
+ Get the Nic handle using any child handle in the IPv6 stack.\r
+\r
+ @param[in] ControllerHandle Pointer to child handle over IPv6.\r
+\r
+ @return NicHandle The pointer to the Nic handle.\r
+ @return NULL Can't find the Nic handle.\r
+\r
+**/\r
+EFI_HANDLE\r
+HttpBootGetNicByIp6Children (\r
+ IN EFI_HANDLE ControllerHandle\r
+ );\r
+\r
/**\r
This function is to convert UINTN to ASCII string with the required formatting.\r
\r
IN EFI_IPv4_ADDRESS *Ip\r
);\r
\r
+/**\r
+ This function is to display the IPv6 address.\r
+\r
+ @param[in] Ip The pointer to the IPv6 address.\r
+\r
+**/\r
+VOID\r
+HttpBootShowIp6Addr (\r
+ IN EFI_IPv6_ADDRESS *Ip\r
+ );\r
+\r
//\r
// A wrapper structure to hold the HTTP headers.\r
//\r
UINT16 LocalPort;\r
} HTTP4_IO_CONFIG_DATA;\r
\r
+//\r
+// HTTP_IO configuration data for IPv6\r
+//\r
+typedef struct {\r
+ EFI_HTTP_VERSION HttpVersion;\r
+ UINT32 RequestTimeOut; // In milliseconds.\r
+ BOOLEAN UseDefaultAddress;\r
+ EFI_IPv6_ADDRESS LocalIp;\r
+ UINT16 LocalPort;\r
+} HTTP6_IO_CONFIG_DATA;\r
+\r
+\r
//\r
// HTTP_IO configuration\r
//\r
typedef union {\r
HTTP4_IO_CONFIG_DATA Config4;\r
+ HTTP6_IO_CONFIG_DATA Config6;\r
} HTTP_IO_CONFIG_DATA;\r
\r
//\r
CHAR8 *Body;\r
} HTTP_IO_RESOPNSE_DATA;\r
\r
+/**\r
+ Retrieve the host address using the EFI_DNS6_PROTOCOL.\r
+\r
+ @param[in] Private The pointer to the driver's private data.\r
+ @param[in] HostName Pointer to buffer containing hostname.\r
+ @param[out] IpAddress On output, pointer to buffer containing IPv6 address.\r
+\r
+ @retval EFI_SUCCESS Operation succeeded.\r
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
+ @retval Others Other errors as indicated. \r
+**/\r
+EFI_STATUS\r
+HttpBootDns (\r
+ IN HTTP_BOOT_PRIVATE_DATA *Private,\r
+ IN CHAR16 *HostName,\r
+ OUT EFI_IPv6_ADDRESS *IpAddress \r
+ );\r
+\r
+/**\r
+ Notify the callback function when an event is triggered.\r
+\r
+ @param[in] Event The triggered event.\r
+ @param[in] Context The opaque parameter to the function.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+HttpBootCommonNotify (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ );\r
+\r
/**\r
Create a HTTP_IO to access the HTTP service. It will create and configure\r
a HTTP child handle.\r
Dns4->Configure (Dns4, NULL);\r
\r
gBS->CloseProtocol (\r
- Dns4Handle,\r
- &gEfiDns4ProtocolGuid,\r
- Service->ImageHandle,\r
- Service->ControllerHandle\r
- );\r
+ Dns4Handle,\r
+ &gEfiDns4ProtocolGuid,\r
+ Service->ImageHandle,\r
+ Service->ControllerHandle\r
+ );\r
}\r
\r
if (Dns4Handle != NULL) {\r
\r
return Status;\r
}\r
+\r
+/**\r
+ Retrieve the host address using the EFI_DNS6_PROTOCOL.\r
+\r
+ @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.\r
+ @param[in] HostName Pointer to buffer containing hostname.\r
+ @param[out] IpAddress On output, pointer to buffer containing IPv6 address.\r
+\r
+ @retval EFI_SUCCESS Operation succeeded.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
+ @retval Others Other errors as indicated.\r
+ \r
+**/\r
+EFI_STATUS\r
+HttpDns6 (\r
+ IN HTTP_PROTOCOL *HttpInstance,\r
+ IN CHAR16 *HostName,\r
+ OUT EFI_IPv6_ADDRESS *IpAddress \r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ HTTP_SERVICE *Service;\r
+ EFI_DNS6_PROTOCOL *Dns6;\r
+ EFI_DNS6_CONFIG_DATA Dns6ConfigData;\r
+ EFI_DNS6_COMPLETION_TOKEN Token;\r
+ EFI_HANDLE Dns6Handle;\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
+ EFI_IPv6_ADDRESS *DnsServerList;\r
+ UINTN DnsServerListCount;\r
+ UINTN DataSize;\r
+ BOOLEAN IsDone;\r
+ \r
+\r
+ Service = HttpInstance->Service;\r
+ ASSERT (Service != NULL);\r
+\r
+ DnsServerList = NULL;\r
+ DnsServerListCount = 0;\r
+ Dns6 = NULL;\r
+ Dns6Handle = NULL;\r
+ ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));\r
+ \r
+ //\r
+ // Get DNS server list from EFI IPv6 Configuration protocol.\r
+ //\r
+ Status = gBS->HandleProtocol (Service->ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config);\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Get the required size.\r
+ //\r
+ DataSize = 0;\r
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL);\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ DnsServerList = AllocatePool (DataSize);\r
+ if (DnsServerList == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ } \r
+\r
+ Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (DnsServerList);\r
+ DnsServerList = NULL;\r
+ } else {\r
+ DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS);\r
+ }\r
+ }\r
+ }\r
+\r
+ //\r
+ // Create a DNSv6 child instance and get the protocol.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ Service->ControllerHandle,\r
+ Service->ImageHandle,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ &Dns6Handle\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ } \r
+ \r
+ Status = gBS->OpenProtocol (\r
+ Dns6Handle,\r
+ &gEfiDns6ProtocolGuid,\r
+ (VOID **) &Dns6,\r
+ Service->ImageHandle,\r
+ Service->ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Configure DNS6 instance for the DNS server address and protocol.\r
+ //\r
+ ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));\r
+ Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount;\r
+ Dns6ConfigData.DnsServerList = DnsServerList;\r
+ Dns6ConfigData.EnableDnsCache = TRUE;\r
+ Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;\r
+ IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &HttpInstance->Ipv6Node.LocalAddress);\r
+ Status = Dns6->Configure (\r
+ Dns6,\r
+ &Dns6ConfigData\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ Token.Status = EFI_NOT_READY;\r
+ IsDone = FALSE;\r
+ //\r
+ // Create event to set the IsDone flag when name resolution is finished.\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpCommonNotify,\r
+ &IsDone,\r
+ &Token.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ //\r
+ // Start asynchronous name resolution.\r
+ //\r
+ Status = Dns6->HostNameToIp (Dns6, HostName, &Token);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Exit;\r
+ }\r
+\r
+ while (!IsDone) {\r
+ Dns6->Poll (Dns6);\r
+ }\r
+\r
+ //\r
+ // Name resolution is done, check result.\r
+ //\r
+ Status = Token.Status; \r
+ if (!EFI_ERROR (Status)) {\r
+ if (Token.RspData.H2AData == NULL) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) {\r
+ Status = EFI_DEVICE_ERROR;\r
+ goto Exit;\r
+ }\r
+ //\r
+ // We just return the first IPv6 address from DNS protocol.\r
+ //\r
+ IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);\r
+ Status = EFI_SUCCESS;\r
+ }\r
+ \r
+Exit:\r
+\r
+ if (Token.Event != NULL) {\r
+ gBS->CloseEvent (Token.Event);\r
+ }\r
+ if (Token.RspData.H2AData != NULL) {\r
+ if (Token.RspData.H2AData->IpList != NULL) {\r
+ FreePool (Token.RspData.H2AData->IpList);\r
+ }\r
+ FreePool (Token.RspData.H2AData);\r
+ }\r
+\r
+ if (Dns6 != NULL) {\r
+ Dns6->Configure (Dns6, NULL);\r
+ \r
+ gBS->CloseProtocol (\r
+ Dns6Handle,\r
+ &gEfiDns6ProtocolGuid,\r
+ Service->ImageHandle,\r
+ Service->ControllerHandle\r
+ );\r
+ }\r
+\r
+ if (Dns6Handle != NULL) {\r
+ NetLibDestroyServiceChild (\r
+ Service->ControllerHandle,\r
+ Service->ImageHandle,\r
+ &gEfiDns6ServiceBindingProtocolGuid,\r
+ Dns6Handle\r
+ );\r
+ }\r
+\r
+ if (DnsServerList != NULL) {\r
+ FreePool (DnsServerList);\r
+ }\r
+ \r
+ return Status; \r
+}\r
OUT EFI_IPv4_ADDRESS *IpAddress \r
);\r
\r
+/**\r
+ Retrieve the host address using the EFI_DNS6_PROTOCOL.\r
+\r
+ @param[in] HttpInstance Pointer to HTTP_PROTOCOL instance.\r
+ @param[in] HostName Pointer to buffer containing hostname.\r
+ @param[out] IpAddress On output, pointer to buffer containing IPv6 address.\r
+\r
+ @retval EFI_SUCCESS Operation succeeded.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
+ @retval EFI_DEVICE_ERROR An unexpected network error occurred.\r
+ @retval Others Other errors as indicated.\r
+ \r
+**/\r
+EFI_STATUS\r
+HttpDns6 (\r
+ IN HTTP_PROTOCOL *HttpInstance,\r
+ IN CHAR16 *HostName,\r
+ OUT EFI_IPv6_ADDRESS *IpAddress \r
+ );\r
+\r
#endif
\ No newline at end of file
///\r
/// Driver Binding Protocol instance\r
///\r
-EFI_DRIVER_BINDING_PROTOCOL gHttpDxeDriverBinding = {\r
- HttpDxeDriverBindingSupported,\r
- HttpDxeDriverBindingStart,\r
- HttpDxeDriverBindingStop,\r
+EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp4DriverBinding = {\r
+ HttpDxeIp4DriverBindingSupported,\r
+ HttpDxeIp4DriverBindingStart,\r
+ HttpDxeIp4DriverBindingStop,\r
HTTP_DRIVER_VERSION,\r
NULL,\r
NULL\r
};\r
\r
+EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp6DriverBinding = {\r
+ HttpDxeIp6DriverBindingSupported,\r
+ HttpDxeIp6DriverBindingStart,\r
+ HttpDxeIp6DriverBindingStop,\r
+ HTTP_DRIVER_VERSION,\r
+ NULL,\r
+ NULL\r
+};\r
+\r
+\r
/**\r
Create a HTTP driver service binding private instance.\r
\r
/**\r
Release all the resource used the HTTP service binding instance.\r
\r
- @param HttpService The HTTP private instance.\r
-\r
+ @param[in] HttpService The HTTP private instance.\r
+ @param[in] UsingIpv6 Indicate use TCP4 protocol or TCP6 protocol.\r
+ if TRUE, use Tcp6 protocol.\r
+ if FALSE, use Tcp4 protocl.\r
**/\r
VOID\r
HttpCleanService (\r
- IN HTTP_SERVICE *HttpService\r
+ IN HTTP_SERVICE *HttpService,\r
+ IN BOOLEAN UsingIpv6\r
)\r
-{\r
+{ \r
+ \r
if (HttpService == NULL) {\r
return ;\r
}\r
-\r
- if (HttpService->TcpChildHandle != NULL) {\r
- gBS->CloseProtocol (\r
- HttpService->TcpChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- HttpService->ImageHandle,\r
- HttpService->ControllerHandle\r
- );\r
-\r
- NetLibDestroyServiceChild (\r
- HttpService->ControllerHandle,\r
- HttpService->ImageHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- HttpService->TcpChildHandle\r
- );\r
+ if (!UsingIpv6) {\r
+ if (HttpService->Tcp4ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpService->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ HttpService->ImageHandle,\r
+ HttpService->ControllerHandle\r
+ );\r
+ \r
+ NetLibDestroyServiceChild (\r
+ HttpService->ControllerHandle,\r
+ HttpService->ImageHandle,\r
+ &gEfiTcp4ServiceBindingProtocolGuid,\r
+ HttpService->Tcp4ChildHandle\r
+ );\r
+ \r
+ HttpService->Tcp4ChildHandle = NULL;\r
+ }\r
+ } else {\r
+ if (HttpService->Tcp6ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpService->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ HttpService->ImageHandle,\r
+ HttpService->ControllerHandle\r
+ );\r
+ \r
+ NetLibDestroyServiceChild (\r
+ HttpService->ControllerHandle,\r
+ HttpService->ImageHandle,\r
+ &gEfiTcp6ServiceBindingProtocolGuid,\r
+ HttpService->Tcp6ChildHandle\r
+ );\r
+ \r
+ HttpService->Tcp6ChildHandle = NULL;\r
+ }\r
}\r
+ \r
}\r
\r
/**\r
in the system.\r
\r
@param[in] Event Not used.\r
- @param[in] Context The pointer to the IP4 config2 instance data.\r
+ @param[in] Context The pointer to the IP4 config2 instance data or IP6 Config instance data.\r
\r
**/\r
VOID\r
NULL, \r
(VOID **) &mHttpUtilities\r
);\r
- \r
+ \r
//\r
// Close the event if Http utilities protocol is loacted.\r
//\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{ \r
+ EFI_STATUS Status;\r
VOID *Registration;\r
\r
gBS->LocateProtocol (\r
//\r
// Install UEFI Driver Model protocol(s).\r
//\r
- return EfiLibInstallDriverBindingComponentName2 (\r
- ImageHandle,\r
- SystemTable,\r
- &gHttpDxeDriverBinding,\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gHttpDxeIp4DriverBinding,\r
+ ImageHandle,\r
+ &gHttpDxeComponentName,\r
+ &gHttpDxeComponentName2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = EfiLibInstallDriverBindingComponentName2 (\r
+ ImageHandle,\r
+ SystemTable,\r
+ &gHttpDxeIp6DriverBinding,\r
+ NULL,\r
+ &gHttpDxeComponentName,\r
+ &gHttpDxeComponentName2\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
ImageHandle,\r
+ &gEfiDriverBindingProtocolGuid,\r
+ &gHttpDxeIp4DriverBinding,\r
+ &gEfiComponentName2ProtocolGuid,\r
+ &gHttpDxeComponentName2,\r
+ &gEfiComponentNameProtocolGuid,\r
&gHttpDxeComponentName,\r
- &gHttpDxeComponentName2\r
+ NULL\r
);\r
+ }\r
+ return Status;\r
}\r
\r
/**\r
return ServiceBinding->DestroyChild (ServiceBinding, HttpInstance->Handle);\r
}\r
\r
+/**\r
+ Test to see if this driver supports ControllerHandle. This is the worker function for\r
+ HttpDxeIp4(6)DriverBindingSupported.\r
+\r
+ @param[in] This The pointer to the driver binding protocol.\r
+ @param[in] ControllerHandle The handle of device to be tested.\r
+ @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
+ device to be started.\r
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
+ \r
+ @retval EFI_SUCCESS This driver supports this device.\r
+ @retval EFI_UNSUPPORTED This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,\r
+ IN UINT8 IpVersion\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GUID *TcpServiceBindingProtocolGuid;\r
+\r
+ if (IpVersion == IP_VERSION_4) {\r
+ TcpServiceBindingProtocolGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
+ } else {\r
+ TcpServiceBindingProtocolGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ TcpServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Start this driver on ControllerHandle. This is the worker function for\r
+ HttpDxeIp4(6)DriverBindingStart.\r
+\r
+ @param[in] This The pointer to the driver binding protocol.\r
+ @param[in] ControllerHandle The handle of device to be started.\r
+ @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
+ device to be started.\r
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
+\r
+\r
+ @retval EFI_SUCCESS This driver is installed to ControllerHandle.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,\r
+ IN UINT8 IpVersion\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ HTTP_SERVICE *HttpService;\r
+ VOID *Interface;\r
+ BOOLEAN UsingIpv6;\r
+\r
+ UsingIpv6 = FALSE;\r
+\r
+ //\r
+ // Test for the Http service binding protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ (VOID **) &ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
+ } else {\r
+ Status = HttpCreateService (ControllerHandle, This->DriverBindingHandle, &HttpService);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ ASSERT (HttpService != NULL);\r
+ \r
+ //\r
+ // Install the HttpServiceBinding Protocol onto Controller\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ControllerHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ &HttpService->ServiceBinding,\r
+ NULL\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ }\r
+\r
+ if (IpVersion == IP_VERSION_4) {\r
+ \r
+ if (HttpService->Tcp4ChildHandle == NULL) {\r
+ //\r
+ // Create a TCP4 child instance, but do not configure it. This will establish the parent-child relationship.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ This->DriverBindingHandle,\r
+ &gEfiTcp4ServiceBindingProtocolGuid,\r
+ &HttpService->Tcp4ChildHandle\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ HttpService->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ &Interface,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ } else {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ } else {\r
+ UsingIpv6 = TRUE;\r
+ \r
+ if (HttpService->Tcp6ChildHandle == NULL) {\r
+ //\r
+ // Create a TCP6 child instance, but do not configure it. This will establish the parent-child relationship.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ This->DriverBindingHandle,\r
+ &gEfiTcp6ServiceBindingProtocolGuid,\r
+ &HttpService->Tcp6ChildHandle\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ HttpService->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ &Interface,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ } else {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ \r
+ON_ERROR:\r
+ \r
+ if (HttpService != NULL) {\r
+ HttpCleanService (HttpService, UsingIpv6);\r
+ if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {\r
+ FreePool (HttpService);\r
+ }\r
+ }\r
+ \r
+ return Status;\r
+\r
+\r
+}\r
+\r
+/**\r
+ Stop this driver on ControllerHandle. This is the worker function for\r
+ HttpDxeIp4(6)DriverBindingStop.\r
+\r
+ @param[in] This Protocol instance pointer.\r
+ @param[in] ControllerHandle Handle of device to stop driver on.\r
+ @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
+ children is zero stop the entire bus driver.\r
+ @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
+\r
+ @retval EFI_SUCCESS This driver was removed ControllerHandle.\r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
+ @retval Others This driver was not removed from this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer,\r
+ IN UINT8 IpVersion\r
+ )\r
+{\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ HTTP_SERVICE *HttpService;\r
+ LIST_ENTRY *List;\r
+ HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
+ BOOLEAN UsingIpv6;\r
+\r
+ //\r
+ // HTTP driver opens TCP4(6) child, So, Controller is a TCP4(6)\r
+ // child handle. Locate the Nic handle first. Then get the\r
+ // HTTP private data back.\r
+ //\r
+ if (IpVersion == IP_VERSION_4) {\r
+ UsingIpv6 = FALSE;\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);\r
+ } else {\r
+ UsingIpv6 = TRUE;\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp6ProtocolGuid);\r
+ }\r
+\r
+ if (NicHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NicHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ (VOID **) &ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ NicHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ \r
+ HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
+ \r
+ if (NumberOfChildren != 0) {\r
+ //\r
+ // Destroy the HTTP child instance in ChildHandleBuffer.\r
+ //\r
+ List = &HttpService->ChildrenList;\r
+ Context.ServiceBinding = ServiceBinding;\r
+ Context.NumberOfChildren = NumberOfChildren;\r
+ Context.ChildHandleBuffer = ChildHandleBuffer;\r
+ Status = NetDestroyLinkList (\r
+ List,\r
+ HttpDestroyChildEntryInHandleBuffer,\r
+ &Context,\r
+ NULL\r
+ );\r
+ } else {\r
+ \r
+ HttpCleanService (HttpService, UsingIpv6);\r
+ \r
+ if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {\r
+ gBS->UninstallProtocolInterface (\r
+ NicHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ ServiceBinding\r
+ );\r
+ FreePool (HttpService);\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ } \r
+ }\r
+ \r
+ return Status;\r
+\r
+}\r
+\r
/**\r
Tests to see if this driver supports a given controller. If a child device is provided, \r
it further tests to see if this driver supports creating a handle for the specified child device.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HttpDxeDriverBindingSupported (\r
+HttpDxeIp4DriverBindingSupported (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE ControllerHandle,\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // Test for the HttpServiceBinding protocol.\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- if (!EFI_ERROR (Status)) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
-\r
- //\r
- // Test for the Tcp4 Protocol\r
- //\r
- return gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
- \r
+ return HttpDxeSupported (\r
+ This,\r
+ ControllerHandle,\r
+ RemainingDevicePath,\r
+ IP_VERSION_4\r
+ );\r
}\r
\r
/**\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HttpDxeDriverBindingStart (\r
+HttpDxeIp4DriverBindingStart (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE ControllerHandle,\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
- HTTP_SERVICE *HttpService;\r
- VOID *Interface;\r
+ return HttpDxeStart (\r
+ This,\r
+ ControllerHandle,\r
+ RemainingDevicePath,\r
+ IP_VERSION_4\r
+ );\r
+}\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
\r
- //\r
- // Test for the Http service binding protocol\r
- //\r
- Status = gBS->OpenProtocol (\r
- ControllerHandle,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- NULL,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
- );\r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
\r
- if (Status == EFI_SUCCESS) {\r
- return EFI_ALREADY_STARTED;\r
- }\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
\r
- Status = HttpCreateService (ControllerHandle, This->DriverBindingHandle, &HttpService);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeIp4DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ )\r
+{\r
+ return HttpDxeStop (\r
+ This,\r
+ ControllerHandle,\r
+ NumberOfChildren,\r
+ ChildHandleBuffer,\r
+ IP_VERSION_4\r
+ );\r
+}\r
\r
- ASSERT (HttpService != NULL);\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
\r
- //\r
- // Create a TCP child instance, but do not configure it. This will establish the parent-child relationship.\r
- //\r
- Status = NetLibCreateServiceChild (\r
- ControllerHandle,\r
- This->DriverBindingHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- &HttpService->TcpChildHandle\r
- );\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
\r
- Status = gBS->OpenProtocol (\r
- HttpService->TcpChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- &Interface,\r
- This->DriverBindingHandle,\r
- ControllerHandle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- \r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeIp6DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{ \r
+ return HttpDxeSupported (\r
+ This,\r
+ ControllerHandle,\r
+ RemainingDevicePath,\r
+ IP_VERSION_6\r
+ );\r
\r
- //\r
- // Install the HttpServiceBinding Protocol onto Controller\r
- //\r
- Status = gBS->InstallMultipleProtocolInterfaces (\r
- &ControllerHandle,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- &HttpService->ServiceBinding,\r
- NULL\r
- );\r
+}\r
\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
+/**\r
+ Starts a device controller or a bus controller.\r
\r
- return EFI_SUCCESS;\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
\r
-ON_ERROR:\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
\r
- if (HttpService != NULL) {\r
- HttpCleanService (HttpService);\r
- FreePool (HttpService);\r
- }\r
- \r
- return Status;\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_ALREADY_STARTED This device is already running on ControllerHandle.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeIp6DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ )\r
+{\r
+ return HttpDxeStart (\r
+ This,\r
+ ControllerHandle,\r
+ RemainingDevicePath,\r
+ IP_VERSION_6\r
+ );\r
}\r
\r
/**\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HttpDxeDriverBindingStop (\r
+HttpDxeIp6DriverBindingStop (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE ControllerHandle,\r
IN UINTN NumberOfChildren,\r
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
)\r
{\r
- EFI_HANDLE NicHandle;\r
- EFI_STATUS Status;\r
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
- HTTP_SERVICE *HttpService;\r
- LIST_ENTRY *List;\r
- HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
- \r
- //\r
- // HTTP driver opens TCP child, So, Controller is a TCP\r
- // child handle. Locate the Nic handle first. Then get the\r
- // HTTP private data back.\r
- //\r
- NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);\r
- if (NicHandle == NULL) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- Status = gBS->OpenProtocol (\r
- NicHandle,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- (VOID **) &ServiceBinding,\r
- This->DriverBindingHandle,\r
- NicHandle,\r
- EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
-\r
- HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
-\r
- if (!IsListEmpty (&HttpService->ChildrenList)) {\r
- //\r
- // Destroy the HTTP child instance in ChildHandleBuffer.\r
- //\r
- List = &HttpService->ChildrenList;\r
- Context.ServiceBinding = ServiceBinding;\r
- Context.NumberOfChildren = NumberOfChildren;\r
- Context.ChildHandleBuffer = ChildHandleBuffer;\r
- Status = NetDestroyLinkList (\r
- List,\r
- HttpDestroyChildEntryInHandleBuffer,\r
- &Context,\r
- NULL\r
- );\r
- }\r
-\r
- if (NumberOfChildren == 0 && IsListEmpty (&HttpService->ChildrenList)) {\r
- gBS->UninstallProtocolInterface (\r
- NicHandle,\r
- &gEfiHttpServiceBindingProtocolGuid,\r
- ServiceBinding\r
+ return HttpDxeStop (\r
+ This,\r
+ ControllerHandle,\r
+ NumberOfChildren,\r
+ ChildHandleBuffer,\r
+ IP_VERSION_6\r
);\r
-\r
- HttpCleanService (HttpService);\r
- \r
- FreePool (HttpService);\r
-\r
- Status = EFI_SUCCESS;\r
- }\r
-\r
- return Status;\r
}\r
-\r
/**\r
Creates a child handle and installs a protocol.\r
\r
HTTP_SERVICE *HttpService;\r
HTTP_PROTOCOL *HttpInstance;\r
EFI_STATUS Status;\r
- VOID *Interface;\r
EFI_TPL OldTpl;\r
\r
if ((This == NULL) || (ChildHandle == NULL)) {\r
if (HttpInstance == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
+ \r
+ HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;\r
+ HttpInstance->Service = HttpService;\r
+ CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));\r
+ NetMapInit (&HttpInstance->TxTokens);\r
+ NetMapInit (&HttpInstance->RxTokens);\r
\r
//\r
// Install HTTP protocol onto ChildHandle\r
goto ON_ERROR;\r
}\r
\r
- HttpInstance->Handle = *ChildHandle;\r
-\r
- Status = HttpInitProtocol (HttpService, HttpInstance);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Open the default Tcp4 protocol by child.\r
- //\r
- Status = gBS->OpenProtocol (\r
- HttpService->TcpChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- (VOID **) &Interface,\r
- gHttpDxeDriverBinding.DriverBindingHandle,\r
- HttpInstance->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
+ HttpInstance->Handle = *ChildHandle;\r
\r
//\r
// Add it to the HTTP service's child list.\r
return EFI_SUCCESS;\r
\r
ON_ERROR:\r
-\r
- HttpCleanProtocol (HttpInstance);\r
+ \r
+ NetMapClean (&HttpInstance->TxTokens);\r
+ NetMapClean (&HttpInstance->RxTokens);\r
FreePool (HttpInstance);\r
\r
return Status;\r
ChildHandle,\r
&gEfiHttpProtocolGuid,\r
(VOID **) &Http,\r
- gHttpDxeDriverBinding.DriverBindingHandle,\r
- ChildHandle,\r
+ NULL,\r
+ NULL,\r
EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
);\r
if (EFI_ERROR (Status)) {\r
return EFI_SUCCESS;\r
}\r
\r
- //\r
- // Close the Tcp4 protocol.\r
- //\r
- gBS->CloseProtocol (\r
- HttpService->TcpChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- gHttpDxeDriverBinding.DriverBindingHandle,\r
- ChildHandle\r
- );\r
- \r
HttpInstance->InDestroy = TRUE;\r
\r
//\r
HttpInstance->InDestroy = FALSE;\r
return Status;\r
}\r
-\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
+ \r
HttpCleanProtocol (HttpInstance);\r
-\r
+ \r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ \r
RemoveEntryList (&HttpInstance->Link);\r
HttpService->ChildrenNumber--;\r
\r
//\r
#include <Protocol/HttpUtilities.h>\r
#include <Protocol/Tcp4.h>\r
+#include <Protocol/Tcp6.h>\r
#include <Protocol/Dns4.h>\r
+#include <Protocol/Dns6.h>\r
#include <Protocol/Ip4Config2.h>\r
+#include <Protocol/Ip6Config.h>\r
+\r
\r
//\r
// Produced Protocols\r
//\r
// Protocol instances\r
//\r
-extern EFI_DRIVER_BINDING_PROTOCOL gHttpDxeDriverBinding;\r
+extern EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp4DriverBinding;\r
+extern EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp6DriverBinding;\r
+\r
extern EFI_COMPONENT_NAME2_PROTOCOL gHttpDxeComponentName2;\r
extern EFI_COMPONENT_NAME_PROTOCOL gHttpDxeComponentName;\r
\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HttpDxeDriverBindingSupported (\r
+HttpDxeIp4DriverBindingSupported (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE ControllerHandle,\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HttpDxeDriverBindingStart (\r
+HttpDxeIp4DriverBindingStart (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE ControllerHandle,\r
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
**/\r
EFI_STATUS\r
EFIAPI\r
-HttpDxeDriverBindingStop (\r
+HttpDxeIp4DriverBindingStop (\r
IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
IN EFI_HANDLE ControllerHandle,\r
IN UINTN NumberOfChildren,\r
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
);\r
\r
+/**\r
+ Tests to see if this driver supports a given controller. If a child device is provided, \r
+ it further tests to see if this driver supports creating a handle for the specified child device.\r
+\r
+ This function checks to see if the driver specified by This supports the device specified by \r
+ ControllerHandle. Drivers will typically use the device path attached to \r
+ ControllerHandle and/or the services from the bus I/O abstraction attached to \r
+ ControllerHandle to determine if the driver supports ControllerHandle. This function \r
+ may be called many times during platform initialization. In order to reduce boot times, the tests \r
+ performed by this function must be very small, and take as little time as possible to execute. This \r
+ function must not change the state of any hardware devices, and this function must be aware that the \r
+ device specified by ControllerHandle may already be managed by the same driver or a \r
+ different driver. This function must match its calls to AllocatePages() with FreePages(), \r
+ AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
+ Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
+ already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
+ to guarantee the state of ControllerHandle is not modified by this function.\r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to test. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For bus drivers, if this parameter is not NULL, then \r
+ the bus driver must determine if the bus controller specified \r
+ by ControllerHandle and the child controller specified \r
+ by RemainingDevicePath are both supported by this \r
+ bus driver.\r
+\r
+ @retval EFI_SUCCESS The device specified by ControllerHandle and\r
+ RemainingDevicePath is supported by the driver specified by This.\r
+ @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by the driver\r
+ specified by This.\r
+ @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
+ RemainingDevicePath is already being managed by a different\r
+ driver or an application that requires exclusive access.\r
+ Currently not implemented.\r
+ @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
+ RemainingDevicePath is not supported by the driver specified by This.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeIp6DriverBindingSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Starts a device controller or a bus controller.\r
+\r
+ The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
+ As a result, much of the error checking on the parameters to Start() has been moved into this \r
+ common boot service. It is legal to call Start() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE.\r
+ 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
+ EFI_DEVICE_PATH_PROTOCOL.\r
+ 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
+ have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
+\r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle The handle of the controller to start. This handle \r
+ must support a protocol interface that supplies \r
+ an I/O abstraction to the driver.\r
+ @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
+ parameter is ignored by device drivers, and is optional for bus \r
+ drivers. For a bus driver, if this parameter is NULL, then handles \r
+ for all the children of Controller are created by this driver. \r
+ If this parameter is not NULL and the first Device Path Node is \r
+ not the End of Device Path Node, then only the handle for the \r
+ child device specified by the first Device Path Node of \r
+ RemainingDevicePath is created by this driver.\r
+ If the first Device Path Node of RemainingDevicePath is \r
+ the End of Device Path Node, no child handle is created by this\r
+ driver.\r
+\r
+ @retval EFI_SUCCESS The device was started.\r
+ @retval EFI_ALREADY_STARTED This device is already running on ControllerHandle.\r
+ @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
+ @retval Others The driver failded to start the device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeIp6DriverBindingStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
+ );\r
+\r
+/**\r
+ Stops a device controller or a bus controller.\r
+ \r
+ The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
+ As a result, much of the error checking on the parameters to Stop() has been moved \r
+ into this common boot service. It is legal to call Stop() from other locations, \r
+ but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
+ 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
+ same driver's Start() function.\r
+ 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
+ EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
+ Start() function, and the Start() function must have called OpenProtocol() on\r
+ ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
+ \r
+ @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
+ @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
+ support a bus specific I/O protocol for the driver \r
+ to use to stop the device.\r
+ @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
+ @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
+ if NumberOfChildren is 0.\r
+\r
+ @retval EFI_SUCCESS The device was stopped.\r
+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeIp6DriverBindingStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
+ );\r
+\r
/**\r
Creates a child handle and installs a protocol.\r
\r
gEfiHttpUtilitiesProtocolGuid ## CONSUMES\r
gEfiTcp4ServiceBindingProtocolGuid ## TO_START\r
gEfiTcp4ProtocolGuid ## TO_START\r
+ gEfiTcp6ServiceBindingProtocolGuid ## TO_START\r
+ gEfiTcp6ProtocolGuid ## TO_START\r
gEfiDns4ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES\r
gEfiDns4ProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiDns6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiDns6ProtocolGuid ## SOMETIMES_CONSUMES\r
gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES\r
+ gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES\r
\r
[UserExtensions.TianoCore."ExtraFiles"]\r
HttpDxeExtra.uni
\ No newline at end of file
)\r
{\r
HTTP_PROTOCOL *HttpInstance;\r
+ EFI_HTTPv4_ACCESS_POINT *Http4AccessPoint;\r
+ EFI_HTTPv6_ACCESS_POINT *Http6AccessPoint;\r
\r
if ((This == NULL) || (HttpConfigData == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
\r
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
ASSERT (HttpInstance != NULL);\r
-\r
+ \r
if (HttpInstance->State < HTTP_STATE_HTTP_CONFIGED) {\r
return EFI_NOT_STARTED;\r
}\r
\r
- if (HttpConfigData->AccessPoint.IPv4Node == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
HttpConfigData->HttpVersion = HttpInstance->HttpVersion;\r
HttpConfigData->TimeOutMillisec = HttpInstance->TimeOutMillisec;\r
HttpConfigData->LocalAddressIsIPv6 = HttpInstance->LocalAddressIsIPv6;\r
\r
- CopyMem (\r
- HttpConfigData->AccessPoint.IPv4Node,\r
- &HttpInstance->IPv4Node,\r
- sizeof (HttpInstance->IPv4Node)\r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ Http6AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv6_ACCESS_POINT));\r
+ CopyMem (\r
+ Http6AccessPoint,\r
+ &HttpInstance->Ipv6Node,\r
+ sizeof (HttpInstance->Ipv6Node)\r
);\r
+ HttpConfigData->AccessPoint.IPv6Node = Http6AccessPoint;\r
+ } else {\r
+ Http4AccessPoint = AllocateZeroPool (sizeof (EFI_HTTPv4_ACCESS_POINT));\r
+ CopyMem (\r
+ Http4AccessPoint,\r
+ &HttpInstance->IPv4Node,\r
+ sizeof (HttpInstance->IPv4Node)\r
+ );\r
+ HttpConfigData->AccessPoint.IPv4Node = Http4AccessPoint;\r
+ }\r
\r
return EFI_SUCCESS;\r
}\r
{\r
HTTP_PROTOCOL *HttpInstance;\r
EFI_STATUS Status;\r
-\r
- if (This == NULL) {\r
+ \r
+ //\r
+ // Check input parameters.\r
+ //\r
+ if (This == NULL || \r
+ (HttpConfigData != NULL && ((HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv6Node == NULL) ||\r
+ (!HttpConfigData->LocalAddressIsIPv6 && HttpConfigData->AccessPoint.IPv4Node == NULL)))) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
ASSERT (HttpInstance != NULL && HttpInstance->Service != NULL);\r
\r
if (HttpConfigData != NULL) {\r
- //\r
- // Check input parameters.\r
- //\r
- if (HttpConfigData->LocalAddressIsIPv6) {\r
- if (HttpConfigData->AccessPoint.IPv6Node == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- } else {\r
- if (HttpConfigData->AccessPoint.IPv4Node == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
+\r
//\r
// Now configure this HTTP instance.\r
//\r
HttpInstance->HttpVersion = HttpConfigData->HttpVersion;\r
HttpInstance->TimeOutMillisec = HttpConfigData->TimeOutMillisec;\r
HttpInstance->LocalAddressIsIPv6 = HttpConfigData->LocalAddressIsIPv6;\r
-\r
- if (HttpConfigData->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
+ \r
+ if (HttpConfigData->LocalAddressIsIPv6) { \r
+ CopyMem (\r
+ &HttpInstance->Ipv6Node,\r
+ HttpConfigData->AccessPoint.IPv6Node,\r
+ sizeof (HttpInstance->Ipv6Node)\r
+ );\r
} else {\r
CopyMem (\r
&HttpInstance->IPv4Node,\r
HttpConfigData->AccessPoint.IPv4Node,\r
sizeof (HttpInstance->IPv4Node)\r
);\r
-\r
- HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;\r
- return EFI_SUCCESS;\r
}\r
+ //\r
+ // Creat Tcp child\r
+ //\r
+ Status = HttpInitProtocol (HttpInstance, HttpInstance->LocalAddressIsIPv6);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ HttpInstance->State = HTTP_STATE_HTTP_CONFIGED;\r
+ return EFI_SUCCESS;\r
\r
} else {\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- } else {\r
- HttpCleanProtocol (HttpInstance);\r
- Status = HttpInitProtocol (HttpInstance->Service, HttpInstance);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- HttpInstance->State = HTTP_STATE_UNCONFIGED;\r
- return EFI_SUCCESS;\r
- }\r
+ //\r
+ // Reset all the resources related to HttpInsance.\r
+ //\r
+ HttpCleanProtocol (HttpInstance);\r
+ HttpInstance->State = HTTP_STATE_UNCONFIGED;\r
+ return EFI_SUCCESS;\r
}\r
}\r
\r
return EFI_NOT_STARTED;\r
}\r
\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
//\r
// Check whether the token already existed.\r
//\r
}\r
FreePool (HttpInstance->Url);\r
HttpInstance->Url = Url; \r
- } \r
+ } \r
+\r
\r
UnicodeStrToAsciiStr (Request->Url, Url);\r
UrlParser = NULL;\r
Wrap->HttpToken = Token;\r
Wrap->HttpInstance = HttpInstance;\r
\r
- Status = HttpCreateTcp4TxEvent (Wrap);\r
+ Status = HttpCreateTcpTxEvent (Wrap);\r
if (EFI_ERROR (Status)) {\r
goto Error1;\r
}\r
\r
if (Configure) {\r
//\r
- // Parse Url for IPv4 address, if failed, perform DNS resolution.\r
+ // Parse Url for IPv4 or IPv6 address, if failed, perform DNS resolution.\r
//\r
- Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Status = NetLibAsciiStrToIp4 (HostName, &HttpInstance->RemoteAddr);\r
+ } else {\r
+ Status = NetLibAsciiStrToIp6 (HostName, &HttpInstance->RemoteIpv6Addr);\r
+ }\r
+\r
if (EFI_ERROR (Status)) {\r
- HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (UINT16));\r
+ HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (CHAR16));\r
if (HostNameStr == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Error1;\r
}\r
-\r
+ \r
AsciiStrToUnicodeStr (HostName, HostNameStr);\r
- Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Status = HttpDns4 (HttpInstance, HostNameStr, &HttpInstance->RemoteAddr);\r
+ } else {\r
+ Status = HttpDns6 (HttpInstance, HostNameStr, &HttpInstance->RemoteIpv6Addr);\r
+ }\r
+ \r
FreePool (HostNameStr);\r
if (EFI_ERROR (Status)) {\r
goto Error1;\r
}\r
}\r
\r
+\r
//\r
// Save the RemotePort and RemoteHost.\r
//\r
//\r
// The request URL is different from previous calls to Request(), close existing TCP instance.\r
//\r
- ASSERT (HttpInstance->Tcp4 != NULL);\r
+ ASSERT (HttpInstance->Tcp4 != NULL &&HttpInstance->Tcp6 != NULL);\r
HttpCloseConnection (HttpInstance);\r
EfiHttpCancel (This, NULL);\r
}\r
Wrap->TcpWrap.Method = Request->Method;\r
\r
if (Configure) {\r
- //\r
- // Configure TCP instance.\r
- //\r
- Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
- if (EFI_ERROR (Status)) {\r
- goto Error1;\r
- }\r
- //\r
- // Connect TCP.\r
- //\r
- Status = HttpConnectTcp4 (HttpInstance);\r
+ Status = HttpInitTcp (HttpInstance, Wrap);\r
if (EFI_ERROR (Status)) {\r
goto Error2;\r
}\r
+\r
} else {\r
//\r
// For the new HTTP token, create TX TCP token events. \r
//\r
- Status = HttpCreateTcp4TxEvent (Wrap);\r
+ Status = HttpCreateTcpTxEvent (Wrap);\r
if (EFI_ERROR (Status)) {\r
goto Error1;\r
}\r
//\r
// Transmit the request message.\r
//\r
- Status = HttpTransmitTcp4 (\r
+ Status = HttpTransmitTcp (\r
HttpInstance,\r
Wrap,\r
(UINT8*) RequestStr,\r
}\r
\r
DispatchDpc ();\r
-\r
+ \r
if (HostName != NULL) {\r
FreePool (HostName);\r
}\r
-\r
+ \r
return EFI_SUCCESS;\r
\r
Error5:\r
Error3:\r
HttpCloseConnection (HttpInstance);\r
\r
-\r
Error2:\r
- HttpCloseTcp4ConnCloseEvent (HttpInstance);\r
- if (NULL != Wrap->TcpWrap.TxToken.CompletionToken.Event) {\r
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
- Wrap->TcpWrap.TxToken.CompletionToken.Event = NULL;\r
+ HttpCloseTcpConnCloseEvent (HttpInstance);\r
+ if (NULL != Wrap->TcpWrap.Tx4Token.CompletionToken.Event) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+ Wrap->TcpWrap.Tx4Token.CompletionToken.Event = NULL;\r
+ }\r
+ if (NULL != Wrap->TcpWrap.Tx6Token.CompletionToken.Event) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+ Wrap->TcpWrap.Tx6Token.CompletionToken.Event = NULL;\r
}\r
\r
Error1:\r
+\r
if (HostName != NULL) {\r
FreePool (HostName);\r
}\r
}\r
\r
/**\r
- Cancel a TxToken or RxToken. \r
+ Cancel a user's Token. \r
\r
@param[in] Map The HTTP instance's token queue.\r
@param[in] Item Object container for one HTTP token and token's wrap.\r
\r
EFI_HTTP_TOKEN *Token;\r
HTTP_TOKEN_WRAP *Wrap;\r
+ HTTP_PROTOCOL *HttpInstance;\r
\r
Token = (EFI_HTTP_TOKEN *) Context;\r
\r
\r
Wrap = (HTTP_TOKEN_WRAP *) Item->Value;\r
ASSERT (Wrap != NULL);\r
+ HttpInstance = Wrap->HttpInstance;\r
\r
//\r
// Free resources.\r
//\r
NetMapRemoveItem (Map, Item, NULL); \r
\r
- if (Wrap->TcpWrap.TxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
- }\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+ }\r
+ \r
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+ }\r
+ \r
+ if (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+ FreePool (Wrap->TcpWrap.Rx4Token.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+ }\r
\r
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
- }\r
+ } else {\r
+ if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+ }\r
+\r
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
+ }\r
\r
- if (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
- FreePool (Wrap->TcpWrap.RxToken.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+ if (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+ FreePool (Wrap->TcpWrap.Rx6Token.Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+ }\r
}\r
\r
+\r
FreePool (Wrap);\r
\r
//\r
Wrap->HttpInstance->NextMsg = Data;\r
\r
//\r
- // Free TxToken since already received corrsponding HTTP response.\r
+ // Free Tx4Token or Tx6Token since already received corrsponding HTTP response.\r
//\r
FreePool (Wrap);\r
\r
\r
@retval EFI_SUCCESS Allocation succeeded.\r
@retval EFI_OUT_OF_RESOURCES Failed to complete the opration due to lack of resources.\r
- @retval EFI_NOT_READY Can't find a corresponding TxToken or \r
+ @retval EFI_NOT_READY Can't find a corresponding Tx4Token/Tx6Token or \r
the EFI_HTTP_UTILITIES_PROTOCOL is not available.\r
\r
**/\r
{\r
EFI_STATUS Status;\r
EFI_HTTP_MESSAGE *HttpMsg;\r
- EFI_TCP4_IO_TOKEN *RxToken;\r
- EFI_TCP4_PROTOCOL *Tcp4;\r
CHAR8 *EndofHeader;\r
CHAR8 *HttpHeaders;\r
UINTN SizeofHeaders;\r
- CHAR8 *Buffer;\r
UINTN BufferSize;\r
UINTN StatusCode;\r
CHAR8 *Tmp;\r
\r
HttpInstance = Wrap->HttpInstance;\r
Token = Wrap->HttpToken;\r
-\r
HttpMsg = Token->Message;\r
\r
- Tcp4 = HttpInstance->Tcp4;\r
- ASSERT (Tcp4 != NULL);\r
- HttpMsg->Headers = NULL;\r
- HttpHeaders = NULL;\r
- SizeofHeaders = 0;\r
- Buffer = NULL;\r
- BufferSize = 0;\r
- EndofHeader = NULL;\r
+ HttpInstance->EndofHeader = NULL;\r
+ HttpInstance->HttpHeaders = NULL;\r
+ HttpMsg->Headers = NULL;\r
+ HttpHeaders = NULL;\r
+ SizeofHeaders = 0;\r
+ BufferSize = 0;\r
+ EndofHeader = NULL;\r
\r
if (HttpMsg->Data.Response != NULL) {\r
//\r
// Need receive the HTTP headers, prepare buffer.\r
//\r
- Status = HttpCreateTcp4RxEventForHeader (HttpInstance);\r
+ Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
if (EFI_ERROR (Status)) {\r
goto Error;\r
}\r
// Check whether we cached the whole HTTP headers.\r
//\r
EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
- }\r
- \r
- RxToken = &HttpInstance->RxToken;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
-\r
- //\r
- // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
- //\r
- while (EndofHeader == NULL) { \r
- HttpInstance->IsRxDone = FALSE;\r
- RxToken->Packet.RxData->DataLength = DEF_BUF_LEN;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
- Status = Tcp4->Receive (Tcp4, RxToken);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
- goto Error;\r
- }\r
- \r
- while (!HttpInstance->IsRxDone) {\r
- Tcp4->Poll (Tcp4);\r
- } \r
-\r
- Status = RxToken->CompletionToken.Status;\r
- if (EFI_ERROR (Status)) {\r
- goto Error;\r
- }\r
-\r
- //\r
- // Append the response string.\r
- //\r
- BufferSize = SizeofHeaders + RxToken->Packet.RxData->FragmentTable[0].FragmentLength;\r
- Buffer = AllocateZeroPool (BufferSize);\r
- if (Buffer == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Error;\r
- }\r
-\r
- if (HttpHeaders != NULL) {\r
- CopyMem (Buffer, HttpHeaders, SizeofHeaders);\r
- FreePool (HttpHeaders);\r
- }\r
-\r
- CopyMem (\r
- Buffer + SizeofHeaders,\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength\r
- );\r
- HttpHeaders = Buffer;\r
- SizeofHeaders = BufferSize;\r
+ } \r
\r
- //\r
- // Check whether we received end of HTTP headers.\r
- //\r
- EndofHeader = AsciiStrStr (HttpHeaders, HTTP_END_OF_HDR_STR); \r
- };\r
+ HttpInstance->EndofHeader = &EndofHeader;\r
+ HttpInstance->HttpHeaders = &HttpHeaders;\r
\r
- //\r
- // Skip the CRLF after the HTTP headers.\r
- //\r
- EndofHeader = EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
+ Status = HttpTcpReceiveHeader (HttpInstance, &SizeofHeaders, &BufferSize);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
\r
//\r
// Cache the part of body.\r
HttpInstance->CacheLen = BodyLen;\r
}\r
\r
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
-\r
//\r
// Search for Status Code.\r
//\r
}\r
\r
//\r
- // The first TxToken not transmitted yet, insert back and return error.\r
+ // The first Tx Token not transmitted yet, insert back and return error.\r
//\r
if (!ValueInItem->TcpWrap.IsTxDone) {\r
goto Error2;\r
//\r
// We still need receive more data when there is no cache data and MsgParser is not NULL;\r
//\r
- RxToken = &Wrap->TcpWrap.RxToken;\r
-\r
- RxToken->Packet.RxData->DataLength = (UINT32) HttpMsg->BodyLength;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) HttpMsg->BodyLength;\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
-\r
- RxToken->CompletionToken.Status = EFI_NOT_READY;\r
- Status = Tcp4->Receive (Tcp4, RxToken);\r
+ Status = HttpTcpReceiveBody (Wrap, HttpMsg);\r
if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
goto Error;\r
}\r
\r
}\r
Token->Status = Status;\r
gBS->SignalEvent (Token->Event);\r
-\r
- if (Wrap != NULL) {\r
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
- }\r
- }\r
- \r
- if (HttpInstance->RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (HttpInstance->RxToken.CompletionToken.Event);\r
- HttpInstance->RxToken.CompletionToken.Event = NULL;\r
- } \r
- \r
+ HttpCloseTcpRxEvent (Wrap);\r
FreePool (Wrap);\r
return Status;\r
\r
NetMapInsertHead (&HttpInstance->TxTokens, ValueInItem->HttpToken, ValueInItem);\r
\r
Error:\r
- if (Wrap != NULL) {\r
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
- }\r
- RxToken = &Wrap->TcpWrap.RxToken;\r
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
- }\r
- FreePool (Wrap);\r
- }\r
-\r
- if (HttpInstance->RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (HttpInstance->RxToken.CompletionToken.Event);\r
- HttpInstance->RxToken.CompletionToken.Event = NULL;\r
- }\r
-\r
- RxToken = &HttpInstance->RxToken;\r
- if (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
- FreePool (RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
- RxToken->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
- }\r
+ HttpTcpTokenCleanup (Wrap);\r
\r
if (HttpHeaders != NULL) {\r
FreePool (HttpHeaders);\r
return EFI_NOT_STARTED;\r
}\r
\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- } \r
-\r
//\r
// Check whether the token already existed.\r
//\r
Wrap->HttpInstance = HttpInstance;\r
Wrap->HttpToken = Token;\r
\r
- Status = HttpCreateTcp4RxEvent (Wrap);\r
+ Status = HttpCreateTcpRxEvent (Wrap);\r
if (EFI_ERROR (Status)) {\r
goto Error;\r
}\r
\r
Error:\r
if (Wrap != NULL) {\r
- if (Wrap->TcpWrap.RxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+ }\r
+\r
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
}\r
FreePool (Wrap);\r
} \r
IN EFI_HTTP_PROTOCOL *This\r
)\r
{\r
- HTTP_PROTOCOL *HttpInstance;\r
EFI_STATUS Status;\r
+ HTTP_PROTOCOL *HttpInstance;\r
\r
if (This == NULL) {\r
return EFI_INVALID_PARAMETER;\r
HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (This);\r
ASSERT (HttpInstance != NULL);\r
\r
- if (HttpInstance->LocalAddressIsIPv6) {\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (HttpInstance->Tcp4 == NULL || HttpInstance->State != HTTP_STATE_TCP_CONNECTED) {\r
+ if (HttpInstance->State != HTTP_STATE_TCP_CONNECTED || (HttpInstance->Tcp4 == NULL && \r
+ HttpInstance->Tcp6 == NULL)) {\r
return EFI_NOT_STARTED;\r
}\r
-\r
- Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
-\r
+ \r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ Status = HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+ } else {\r
+ Status = HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+ }\r
+ \r
DispatchDpc ();\r
-\r
+ \r
return Status;\r
}\r
}\r
\r
/**\r
- The notify function associated with TxToken for Tcp4->Transmit().\r
+ The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
\r
@param[in] Context The context.\r
\r
)\r
{\r
HTTP_TOKEN_WRAP *Wrap;\r
+ HTTP_PROTOCOL *HttpInstance;\r
\r
if (Context == NULL) {\r
return ;\r
}\r
+ \r
+ Wrap = (HTTP_TOKEN_WRAP *) Context;\r
+ HttpInstance = Wrap->HttpInstance;\r
+ \r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;\r
+ gBS->SignalEvent (Wrap->HttpToken->Event);\r
+\r
+ //\r
+ // Free resources.\r
+ //\r
+ if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+ FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
+ }\r
\r
- Wrap = (HTTP_TOKEN_WRAP *) Context;\r
- Wrap->HttpToken->Status = Wrap->TcpWrap.TxToken.CompletionToken.Status;\r
- gBS->SignalEvent (Wrap->HttpToken->Event);\r
+ if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+ }\r
+ \r
+ } else {\r
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
+ gBS->SignalEvent (Wrap->HttpToken->Event);\r
+ \r
+ //\r
+ // Free resources.\r
+ //\r
+ if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+ FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
+ }\r
\r
- //\r
- // Free resources.\r
- //\r
- if (Wrap->TcpWrap.TxToken.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
- FreePool (Wrap->TcpWrap.TxToken.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
+ if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+ } \r
}\r
\r
- if (Wrap->TcpWrap.TxToken.CompletionToken.Event != NULL) {\r
- gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
- }\r
\r
Wrap->TcpWrap.IsTxDone = TRUE;\r
\r
QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);\r
}\r
\r
-\r
/**\r
- The notify function associated with RxToken for Tcp4->Receive ().\r
+ The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
\r
@param[in] Context The context.\r
\r
UINTN Length;\r
EFI_STATUS Status;\r
HTTP_PROTOCOL *HttpInstance;\r
+ BOOLEAN UsingIpv6;\r
\r
if (Context == NULL) {\r
return ;\r
}\r
\r
Wrap = (HTTP_TOKEN_WRAP *) Context;\r
- gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
- if (EFI_ERROR (Wrap->TcpWrap.RxToken.CompletionToken.Status)) {\r
- return ;\r
- }\r
-\r
HttpInstance = Wrap->HttpInstance;\r
+ UsingIpv6 = HttpInstance->LocalAddressIsIPv6;\r
+ \r
+ if (UsingIpv6) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
+ \r
+ if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
+ return ;\r
+ }\r
+\r
+ } else {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+ \r
+ if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
+ return ;\r
+ }\r
+ }\r
\r
//\r
// Check whether we receive a complete HTTP message.\r
//\r
ASSERT (HttpInstance->MsgParser != NULL);\r
+ if (UsingIpv6) {\r
+ Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
+ } else {\r
+ Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
+ }\r
\r
- Length = (UINTN) Wrap->TcpWrap.RxData.FragmentTable[0].FragmentLength;\r
Status = HttpParseMessageBody (\r
HttpInstance->MsgParser,\r
Length,\r
\r
\r
Wrap->TcpWrap.IsRxDone = TRUE;\r
- Wrap->HttpToken->Status = Wrap->TcpWrap.RxToken.CompletionToken.Status;\r
+ if (UsingIpv6) {\r
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
+ } else {\r
+ Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
+ }\r
+ \r
\r
gBS->SignalEvent (Wrap->HttpToken->Event);\r
\r
QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);\r
}\r
\r
-\r
/**\r
- Create events for the TCP4 connection token and TCP4 close token.\r
+ Create events for the TCP connection token and TCP close token.\r
\r
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
\r
\r
**/\r
EFI_STATUS\r
-HttpCreateTcp4ConnCloseEvent (\r
+HttpCreateTcpConnCloseEvent (\r
IN HTTP_PROTOCOL *HttpInstance\r
)\r
{\r
EFI_STATUS Status;\r
+\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
//\r
// Create events for variuos asynchronous operations.\r
//\r
EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
HttpCommonNotify,\r
- &HttpInstance->IsConnDone,\r
- &HttpInstance->ConnToken.CompletionToken.Event\r
+ &HttpInstance->IsTcp4ConnDone,\r
+ &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
);\r
if (EFI_ERROR (Status)) {\r
goto ERROR;\r
}\r
\r
//\r
- // Initialize CloseToken\r
+ // Initialize Tcp4CloseToken\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpCommonNotify,\r
+ &HttpInstance->IsTcp4CloseDone,\r
+ &HttpInstance->Tcp4CloseToken.CompletionToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR;\r
+ }\r
+ \r
+ } else {\r
+ //\r
+ // Create events for variuos asynchronous operations.\r
//\r
Status = gBS->CreateEvent (\r
EVT_NOTIFY_SIGNAL,\r
TPL_NOTIFY,\r
HttpCommonNotify,\r
- &HttpInstance->IsCloseDone,\r
- &HttpInstance->CloseToken.CompletionToken.Event\r
+ &HttpInstance->IsTcp6ConnDone,\r
+ &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
);\r
if (EFI_ERROR (Status)) {\r
goto ERROR;\r
}\r
\r
- \r
+ //\r
+ // Initialize Tcp6CloseToken\r
+ //\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpCommonNotify,\r
+ &HttpInstance->IsTcp6CloseDone,\r
+ &HttpInstance->Tcp6CloseToken.CompletionToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR;\r
+ }\r
+ }\r
+ \r
return EFI_SUCCESS;\r
\r
ERROR:\r
//\r
// Error handling\r
//\r
- HttpCloseTcp4ConnCloseEvent (HttpInstance);\r
+ HttpCloseTcpConnCloseEvent (HttpInstance);\r
\r
return Status;\r
}\r
\r
\r
/**\r
- Close events in the TCP4 connection token and TCP4 close token.\r
+ Close events in the TCP connection token and TCP close token.\r
\r
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
\r
**/\r
VOID\r
-HttpCloseTcp4ConnCloseEvent (\r
+HttpCloseTcpConnCloseEvent (\r
IN HTTP_PROTOCOL *HttpInstance\r
)\r
{\r
ASSERT (HttpInstance != NULL);\r
\r
- if (NULL != HttpInstance->ConnToken.CompletionToken.Event) {\r
- gBS->CloseEvent (HttpInstance->ConnToken.CompletionToken.Event);\r
- HttpInstance->ConnToken.CompletionToken.Event = NULL;\r
- }\r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {\r
+ gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);\r
+ HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;\r
+ }\r
\r
- if (NULL != HttpInstance->CloseToken.CompletionToken.Event) {\r
- gBS->CloseEvent(HttpInstance->CloseToken.CompletionToken.Event);\r
- HttpInstance->CloseToken.CompletionToken.Event = NULL;\r
- } \r
+ if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {\r
+ gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);\r
+ HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;\r
+ }\r
+\r
+ } else {\r
+ if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {\r
+ gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);\r
+ HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;\r
+ }\r
+\r
+ if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {\r
+ gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);\r
+ HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;\r
+ }\r
+ }\r
+ \r
}\r
\r
/**\r
- Create event for the TCP4 transmit token.\r
+ Create event for the TCP transmit token.\r
\r
@param[in] Wrap Point to HTTP token's wrap data.\r
\r
\r
**/\r
EFI_STATUS\r
-HttpCreateTcp4TxEvent (\r
+HttpCreateTcpTxEvent (\r
IN HTTP_TOKEN_WRAP *Wrap\r
)\r
{\r
EFI_STATUS Status;\r
+ HTTP_PROTOCOL *HttpInstance;\r
HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
\r
+ HttpInstance = Wrap->HttpInstance;\r
TcpWrap = &Wrap->TcpWrap;\r
\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- HttpTcpTransmitNotify,\r
- Wrap,\r
- &TcpWrap->TxToken.CompletionToken.Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpTcpTransmitNotify,\r
+ Wrap,\r
+ &TcpWrap->Tx4Token.CompletionToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ TcpWrap->Tx4Data.Push = TRUE;\r
+ TcpWrap->Tx4Data.Urgent = FALSE;\r
+ TcpWrap->Tx4Data.FragmentCount = 1;\r
+ TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;\r
+ TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;\r
\r
- TcpWrap->TxData.Push = TRUE;\r
- TcpWrap->TxData.Urgent = FALSE;\r
- TcpWrap->TxData.FragmentCount = 1;\r
- TcpWrap->TxToken.Packet.TxData = &Wrap->TcpWrap.TxData;\r
- TcpWrap->TxToken.CompletionToken.Status = EFI_NOT_READY;\r
+ } else {\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpTcpTransmitNotify,\r
+ Wrap,\r
+ &TcpWrap->Tx6Token.CompletionToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
\r
+ TcpWrap->Tx6Data.Push = TRUE;\r
+ TcpWrap->Tx6Data.Urgent = FALSE;\r
+ TcpWrap->Tx6Data.FragmentCount = 1;\r
+ TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;\r
+ TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;\r
+ \r
+ \r
+ }\r
+ \r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Create event for the TCP4 receive token which is used to receive HTTP header.\r
+ Create event for the TCP receive token which is used to receive HTTP header.\r
\r
@param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
\r
\r
**/\r
EFI_STATUS\r
-HttpCreateTcp4RxEventForHeader (\r
+HttpCreateTcpRxEventForHeader (\r
IN HTTP_PROTOCOL *HttpInstance\r
)\r
{\r
EFI_STATUS Status;\r
\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpCommonNotify,\r
+ &HttpInstance->IsRxDone,\r
+ &HttpInstance->Rx4Token.CompletionToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ HttpInstance->Rx4Data.FragmentCount = 1;\r
+ HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
+ HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- HttpCommonNotify,\r
- &HttpInstance->IsRxDone,\r
- &HttpInstance->RxToken.CompletionToken.Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ } else {\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpCommonNotify,\r
+ &HttpInstance->IsRxDone,\r
+ &HttpInstance->Rx6Token.CompletionToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ HttpInstance->Rx6Data.FragmentCount =1;\r
+ HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;\r
+ HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
+ \r
}\r
\r
- HttpInstance->RxData.FragmentCount = 1;\r
- HttpInstance->RxToken.Packet.RxData = &HttpInstance->RxData;\r
- HttpInstance->RxToken.CompletionToken.Status = EFI_NOT_READY;\r
\r
return EFI_SUCCESS;\r
}\r
\r
/**\r
- Create event for the TCP4 receive token which is used to receive HTTP body.\r
+ Create event for the TCP receive token which is used to receive HTTP body.\r
\r
@param[in] Wrap Point to HTTP token's wrap data.\r
\r
\r
**/\r
EFI_STATUS\r
-HttpCreateTcp4RxEvent (\r
+HttpCreateTcpRxEvent (\r
IN HTTP_TOKEN_WRAP *Wrap \r
)\r
{\r
EFI_STATUS Status;\r
+ HTTP_PROTOCOL *HttpInstance;\r
HTTP_TCP_TOKEN_WRAP *TcpWrap;\r
\r
+ HttpInstance = Wrap->HttpInstance;\r
TcpWrap = &Wrap->TcpWrap;\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpTcpReceiveNotify,\r
+ Wrap,\r
+ &TcpWrap->Rx4Token.CompletionToken.Event\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ TcpWrap->Rx4Data.FragmentCount = 1;\r
+ TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
+ TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
\r
- Status = gBS->CreateEvent (\r
- EVT_NOTIFY_SIGNAL,\r
- TPL_NOTIFY,\r
- HttpTcpReceiveNotify,\r
- Wrap,\r
- &TcpWrap->RxToken.CompletionToken.Event\r
- );\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ } else {\r
+ Status = gBS->CreateEvent (\r
+ EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ HttpTcpReceiveNotify,\r
+ Wrap,\r
+ &TcpWrap->Rx6Token.CompletionToken.Event\r
+ ); \r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ TcpWrap->Rx6Data.FragmentCount = 1;\r
+ TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;\r
+ TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
}\r
+ \r
+ return EFI_SUCCESS;\r
+}\r
\r
- TcpWrap->RxData.FragmentCount = 1;\r
- TcpWrap->RxToken.Packet.RxData = &Wrap->TcpWrap.RxData;\r
- TcpWrap->RxToken.CompletionToken.Status = EFI_NOT_READY;\r
+/**\r
+ Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
\r
- return EFI_SUCCESS;\r
+ @param[in] Wrap Pointer to HTTP token's wrap data.\r
+ \r
+**/\r
+VOID\r
+HttpCloseTcpRxEvent (\r
+ IN HTTP_TOKEN_WRAP *Wrap\r
+ )\r
+{\r
+ HTTP_PROTOCOL *HttpInstance;\r
+ EFI_TCP4_IO_TOKEN *Rx4Token;\r
+ EFI_TCP6_IO_TOKEN *Rx6Token;\r
+\r
+ HttpInstance = Wrap->HttpInstance;\r
+ Rx4Token = NULL;\r
+ Rx6Token = NULL;\r
+ \r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ if (Wrap != NULL) {\r
+ if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
+ } \r
+ }\r
+\r
+ if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
+ HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
+ }\r
+ } else {\r
+ if (Wrap != NULL) {\r
+ if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+ }\r
+ }\r
+ \r
+ if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
+ gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
+ HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
+ }\r
+ }\r
}\r
\r
/**\r
Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
\r
- @param[in] HttpSb The HTTP service private instance.\r
@param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.\r
+ @param[in] IpVersion Indicate us TCP4 protocol or TCP6 protocol.\r
\r
@retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully. \r
@retval Others Other error as indicated.\r
**/\r
EFI_STATUS\r
HttpInitProtocol (\r
- IN HTTP_SERVICE *HttpSb,\r
- IN OUT HTTP_PROTOCOL *HttpInstance\r
+ IN OUT HTTP_PROTOCOL *HttpInstance,\r
+ IN BOOLEAN IpVersion\r
)\r
{\r
EFI_STATUS Status;\r
VOID *Interface;\r
+ BOOLEAN UsingIpv6;\r
+ \r
+ ASSERT (HttpInstance != NULL);\r
+ UsingIpv6 = IpVersion;\r
+ \r
+ if (!UsingIpv6) {\r
+ //\r
+ // Create TCP4 child.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ HttpInstance->Service->ControllerHandle,\r
+ HttpInstance->Service->ImageHandle,\r
+ &gEfiTcp4ServiceBindingProtocolGuid,\r
+ &HttpInstance->Tcp4ChildHandle\r
+ );\r
\r
- ASSERT ((HttpSb != NULL) && (HttpInstance != NULL));\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
- HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;\r
- CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));\r
- HttpInstance->Service = HttpSb;\r
+ Status = gBS->OpenProtocol (\r
+ HttpInstance->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ (VOID **) &Interface,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Service->ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
- //\r
- // Create TCP child.\r
- //\r
- Status = NetLibCreateServiceChild (\r
- HttpInstance->Service->ControllerHandle,\r
- HttpInstance->Service->ImageHandle,\r
- &gEfiTcp4ServiceBindingProtocolGuid,\r
- &HttpInstance->TcpChildHandle\r
- );\r
+ Status = gBS->OpenProtocol (\r
+ HttpInstance->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ (VOID **) &HttpInstance->Tcp4,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
+ Status = gBS->OpenProtocol (\r
+ HttpInstance->Service->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ (VOID **) &Interface,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ } else {\r
+ //\r
+ // Create TCP6 Child.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ HttpInstance->Service->ControllerHandle,\r
+ HttpInstance->Service->ImageHandle,\r
+ &gEfiTcp6ServiceBindingProtocolGuid,\r
+ &HttpInstance->Tcp6ChildHandle\r
+ );\r
\r
- Status = gBS->OpenProtocol (\r
- HttpInstance->TcpChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- (VOID **) &Interface,\r
- HttpInstance->Service->ImageHandle,\r
- HttpInstance->Service->ControllerHandle,\r
- EFI_OPEN_PROTOCOL_BY_DRIVER\r
- );\r
- \r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
\r
- Status = gBS->OpenProtocol (\r
- HttpInstance->TcpChildHandle,\r
- &gEfiTcp4ProtocolGuid,\r
- (VOID **) &HttpInstance->Tcp4,\r
- HttpInstance->Service->ImageHandle,\r
- HttpInstance->Handle,\r
- EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
- );\r
- if (EFI_ERROR(Status)) {\r
- goto ON_ERROR;\r
- }\r
+ Status = gBS->OpenProtocol (\r
+ HttpInstance->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ (VOID **) &Interface,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Service->ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ HttpInstance->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ (VOID **) &HttpInstance->Tcp6,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ \r
+ if (EFI_ERROR(Status)) {\r
+ goto ON_ERROR;\r
+ } \r
+\r
+ Status = gBS->OpenProtocol (\r
+ HttpInstance->Service->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ (VOID **) &Interface,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
\r
+ if (EFI_ERROR(Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ }\r
+ \r
HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
if (HttpInstance->Url == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ON_ERROR;\r
}\r
\r
- NetMapInit (&HttpInstance->TxTokens);\r
- NetMapInit (&HttpInstance->RxTokens);\r
-\r
return EFI_SUCCESS;\r
\r
ON_ERROR:\r
\r
- if (HttpInstance->TcpChildHandle != NULL) {\r
+ if (HttpInstance->Tcp4ChildHandle != NULL) {\r
gBS->CloseProtocol (\r
- HttpInstance->TcpChildHandle,\r
+ HttpInstance->Tcp4ChildHandle,\r
&gEfiTcp4ProtocolGuid,\r
HttpInstance->Service->ImageHandle,\r
HttpInstance->Service->ControllerHandle\r
);\r
\r
gBS->CloseProtocol (\r
- HttpInstance->TcpChildHandle,\r
+ HttpInstance->Tcp4ChildHandle,\r
&gEfiTcp4ProtocolGuid,\r
HttpInstance->Service->ImageHandle,\r
HttpInstance->Handle\r
- );\r
+ ); \r
\r
NetLibDestroyServiceChild (\r
HttpInstance->Service->ControllerHandle,\r
HttpInstance->Service->ImageHandle,\r
&gEfiTcp4ServiceBindingProtocolGuid,\r
- HttpInstance->TcpChildHandle\r
+ HttpInstance->Tcp4ChildHandle\r
);\r
}\r
+ \r
+ if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Service->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle\r
+ );\r
+ }\r
+ \r
+ if (HttpInstance->Tcp6ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Service->ControllerHandle\r
+ );\r
\r
- return Status;\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle\r
+ );\r
+ \r
+ NetLibDestroyServiceChild (\r
+ HttpInstance->Service->ControllerHandle,\r
+ HttpInstance->Service->ImageHandle,\r
+ &gEfiTcp6ServiceBindingProtocolGuid,\r
+ HttpInstance->Tcp6ChildHandle\r
+ );\r
+ }\r
+ \r
+ if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Service->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle\r
+ );\r
+ }\r
+\r
+ return EFI_UNSUPPORTED;\r
\r
}\r
\r
{\r
HttpCloseConnection (HttpInstance);\r
\r
- HttpCloseTcp4ConnCloseEvent (HttpInstance);\r
+ HttpCloseTcpConnCloseEvent (HttpInstance);\r
\r
if (HttpInstance->CacheBody != NULL) {\r
FreePool (HttpInstance->CacheBody);\r
HttpFreeMsgParser (HttpInstance->MsgParser);\r
HttpInstance->MsgParser = NULL;\r
}\r
-\r
+ \r
if (HttpInstance->Url != NULL) {\r
FreePool (HttpInstance->Url);\r
HttpInstance->Url = NULL;\r
}\r
-\r
+ \r
NetMapClean (&HttpInstance->TxTokens);\r
NetMapClean (&HttpInstance->RxTokens);\r
\r
- if (HttpInstance->TcpChildHandle != NULL) {\r
+ if (HttpInstance->Tcp4ChildHandle != NULL) {\r
gBS->CloseProtocol (\r
- HttpInstance->TcpChildHandle,\r
+ HttpInstance->Tcp4ChildHandle,\r
&gEfiTcp4ProtocolGuid,\r
HttpInstance->Service->ImageHandle,\r
HttpInstance->Service->ControllerHandle\r
);\r
\r
gBS->CloseProtocol (\r
- HttpInstance->TcpChildHandle,\r
+ HttpInstance->Tcp4ChildHandle,\r
&gEfiTcp4ProtocolGuid,\r
HttpInstance->Service->ImageHandle,\r
HttpInstance->Handle\r
HttpInstance->Service->ControllerHandle,\r
HttpInstance->Service->ImageHandle,\r
&gEfiTcp4ServiceBindingProtocolGuid,\r
- HttpInstance->TcpChildHandle\r
+ HttpInstance->Tcp4ChildHandle\r
);\r
}\r
+\r
+ if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Service->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle\r
+ );\r
+ } \r
+\r
+ if (HttpInstance->Tcp6ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Service->ControllerHandle\r
+ );\r
+\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle\r
+ );\r
+ \r
+ NetLibDestroyServiceChild (\r
+ HttpInstance->Service->ControllerHandle,\r
+ HttpInstance->Service->ImageHandle,\r
+ &gEfiTcp6ServiceBindingProtocolGuid,\r
+ HttpInstance->Tcp6ChildHandle\r
+ );\r
+ }\r
+ \r
+ if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
+ gBS->CloseProtocol (\r
+ HttpInstance->Service->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ HttpInstance->Service->ImageHandle,\r
+ HttpInstance->Handle\r
+ );\r
+ }\r
+ \r
}\r
\r
/**\r
{\r
EFI_STATUS Status;\r
\r
- //\r
- // Create events for variuos asynchronous operations.\r
- //\r
- HttpInstance->IsConnDone = FALSE;\r
-\r
//\r
// Connect to Http server\r
//\r
- HttpInstance->ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
- Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->ConnToken);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
- return Status;\r
- }\r
-\r
- while (!HttpInstance->IsConnDone) {\r
- HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
- }\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ HttpInstance->IsTcp4ConnDone = FALSE;\r
+ HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
+ Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
+ return Status;\r
+ }\r
+ \r
+ while (!HttpInstance->IsTcp4ConnDone) {\r
+ HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+ }\r
+ \r
+ Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
+ \r
+ } else {\r
+ HttpInstance->IsTcp6ConnDone = FALSE;\r
+ HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
+ Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
+ return Status;\r
+ }\r
\r
- Status = HttpInstance->ConnToken.CompletionToken.Status;\r
+ while(!HttpInstance->IsTcp6ConnDone) {\r
+ HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+ }\r
\r
+ Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status; \r
+ }\r
+ \r
if (!EFI_ERROR (Status)) {\r
HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
}\r
EFI_STATUS Status;\r
\r
if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
- HttpInstance->CloseToken.AbortOnClose = TRUE;\r
- HttpInstance->IsCloseDone = FALSE;\r
- \r
- Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->CloseToken);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
\r
- while (!HttpInstance->IsCloseDone) {\r
- HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
+ HttpInstance->IsTcp6CloseDone = FALSE;\r
+ Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (!HttpInstance->IsTcp6CloseDone) {\r
+ HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+ }\r
+ \r
+ } else {\r
+ HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
+ HttpInstance->IsTcp4CloseDone = FALSE;\r
+ Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ while (!HttpInstance->IsTcp4CloseDone) {\r
+ HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+ }\r
}\r
+\r
}\r
\r
HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
return Status;\r
}\r
\r
- Status = HttpCreateTcp4ConnCloseEvent (HttpInstance);\r
+ Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = HttpCreateTcpTxEvent (Wrap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Configure TCP6 protocol child.\r
+\r
+ @param[in] HttpInstance The HTTP instance private data.\r
+ @param[in] Wrap The HTTP token's wrap data.\r
+\r
+ @retval EFI_SUCCESS The TCP6 protocol child is configured.\r
+ @retval Others Other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpConfigureTcp6 (\r
+ IN HTTP_PROTOCOL *HttpInstance,\r
+ IN HTTP_TOKEN_WRAP *Wrap\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TCP6_CONFIG_DATA *Tcp6CfgData;\r
+ EFI_TCP6_ACCESS_POINT *Tcp6Ap;\r
+ EFI_TCP6_OPTION *Tcp6Option;\r
+ \r
+ ASSERT (HttpInstance != NULL);\r
+ \r
+ Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
+ ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
+\r
+ Tcp6CfgData->TrafficClass = 0;\r
+ Tcp6CfgData->HopLimit = 255;\r
+ Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
+ \r
+ Tcp6Ap = &Tcp6CfgData->AccessPoint;\r
+ Tcp6Ap->ActiveFlag = TRUE;\r
+ Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
+ Tcp6Ap->RemotePort = HttpInstance->RemotePort;\r
+ IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
+ IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
+\r
+ Tcp6Option = Tcp6CfgData->ControlOption;\r
+ Tcp6Option->ReceiveBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
+ Tcp6Option->SendBufferSize = HTTP_BUFFER_SIZE_DEAULT;\r
+ Tcp6Option->MaxSynBackLog = HTTP_MAX_SYN_BACK_LOG;\r
+ Tcp6Option->ConnectionTimeout = HTTP_CONNECTION_TIMEOUT;\r
+ Tcp6Option->DataRetries = HTTP_DATA_RETRIES;\r
+ Tcp6Option->FinTimeout = HTTP_FIN_TIMEOUT;\r
+ Tcp6Option->KeepAliveProbes = HTTP_KEEP_ALIVE_PROBES;\r
+ Tcp6Option->KeepAliveTime = HTTP_KEEP_ALIVE_TIME;\r
+ Tcp6Option->KeepAliveInterval = HTTP_KEEP_ALIVE_INTERVAL;\r
+ Tcp6Option->EnableNagle = TRUE;\r
+\r
+ Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
+ return Status;\r
+ }\r
+ \r
+ Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Status = HttpCreateTcp4TxEvent (Wrap);\r
+ Status = HttpCreateTcpTxEvent (Wrap);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
\r
return EFI_SUCCESS;\r
+ \r
}\r
\r
/**\r
- Check existing TCP connection, if in error state, receover TCP4 connection.\r
+ Check existing TCP connection, if in error state, recover TCP4 connection.\r
\r
@param[in] HttpInstance The HTTP instance private data.\r
\r
}\r
\r
/**\r
- Send the HTTP message through TCP4.\r
+ Check existing TCP connection, if in error state, recover TCP6 connection.\r
+\r
+ @param[in] HttpInstance The HTTP instance private data.\r
+\r
+ @retval EFI_SUCCESS The TCP connection is established.\r
+ @retval EFI_NOT_READY TCP6 protocol child is not created or configured.\r
+ @retval Others Other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpConnectTcp6 (\r
+ IN HTTP_PROTOCOL *HttpInstance\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TCP6_CONNECTION_STATE Tcp6State;\r
+\r
+ if (HttpInstance->State != HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
+ return EFI_NOT_READY;\r
+ }\r
+\r
+ Status = HttpInstance->Tcp6->GetModeData (\r
+ HttpInstance->Tcp6,\r
+ &Tcp6State,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL\r
+ );\r
+ \r
+ if (EFI_ERROR(Status)){\r
+ DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
+ return Status;\r
+ }\r
+\r
+ if (Tcp6State > Tcp6StateEstablished) {\r
+ HttpCloseConnection (HttpInstance);\r
+ }\r
+\r
+ return HttpCreateConnection (HttpInstance);\r
+}\r
+\r
+/**\r
+ Initialize TCP related data.\r
+\r
+ @param[in] HttpInstance The HTTP instance private data.\r
+ @param[in] Wrap The HTTP token's wrap data.\r
+\r
+ @retval EFI_SUCCESS The initialization of TCP instance is done. \r
+ @retval Others Other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpInitTcp (\r
+ IN HTTP_PROTOCOL *HttpInstance,\r
+ IN HTTP_TOKEN_WRAP *Wrap\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ ASSERT (HttpInstance != NULL);\r
+\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ //\r
+ // Configure TCP instance.\r
+ //\r
+ Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Connect TCP.\r
+ //\r
+ Status = HttpConnectTcp4 (HttpInstance);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ } else {\r
+ //\r
+ // Configure TCP instance.\r
+ //\r
+ Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ //\r
+ // Connect TCP.\r
+ //\r
+ Status = HttpConnectTcp6 (HttpInstance);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ \r
+ return EFI_SUCCESS;\r
+ \r
+}\r
+\r
+/**\r
+ Send the HTTP message through TCP4 or TCP6.\r
\r
@param[in] HttpInstance The HTTP instance private data.\r
@param[in] Wrap The HTTP token's wrap data.\r
\r
**/\r
EFI_STATUS\r
-HttpTransmitTcp4 (\r
+HttpTransmitTcp (\r
IN HTTP_PROTOCOL *HttpInstance,\r
IN HTTP_TOKEN_WRAP *Wrap,\r
IN UINT8 *TxString,\r
)\r
{\r
EFI_STATUS Status;\r
- EFI_TCP4_IO_TOKEN *TxToken;\r
+ EFI_TCP4_IO_TOKEN *Tx4Token;\r
EFI_TCP4_PROTOCOL *Tcp4;\r
+ EFI_TCP6_IO_TOKEN *Tx6Token;\r
+ EFI_TCP6_PROTOCOL *Tcp6;\r
\r
- Tcp4 = HttpInstance->Tcp4;\r
- TxToken = &Wrap->TcpWrap.TxToken;\r
+ if (!HttpInstance->LocalAddressIsIPv6) { \r
+ Tcp4 = HttpInstance->Tcp4;\r
+ Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
+ \r
+ Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
+ Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
+ Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
+ Tx4Token->CompletionToken.Status = EFI_NOT_READY; \r
+ \r
+ Wrap->TcpWrap.IsTxDone = FALSE;\r
+ Status = Tcp4->Transmit (Tcp4, Tx4Token);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
+ return Status;\r
+ }\r
\r
- TxToken->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
- TxToken->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
- TxToken->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
- TxToken->CompletionToken.Status = EFI_NOT_READY; \r
+ } else {\r
+ Tcp6 = HttpInstance->Tcp6;\r
+ Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
\r
- Wrap->TcpWrap.IsTxDone = FALSE;\r
- Status = Tcp4->Transmit (Tcp4, TxToken);\r
- if (EFI_ERROR (Status)) {\r
- DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
- return Status;\r
+ Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
+ Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
+ Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
+ Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
+\r
+ Wrap->TcpWrap.IsTxDone = FALSE;\r
+ Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
+ return Status;\r
+ }\r
}\r
+ \r
\r
return Status;\r
}\r
\r
/**\r
Check whether the user's token or event has already\r
- been enqueue on HTTP TxToken or RxToken list.\r
+ been enqueue on HTTP Tx or Rx Token list.\r
\r
@param[in] Map The container of either user's transmit or receive\r
token.\r
}\r
\r
/**\r
- Check whether the HTTP message associated with TxToken is already sent out.\r
+ Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
\r
- @param[in] Map The container of TxToken.\r
+ @param[in] Map The container of Tx4Token or Tx6Token.\r
@param[in] Item Current item to check against.\r
@param[in] Context The Token to check againist.\r
\r
/**\r
Transmit the HTTP mssage by processing the associated HTTP token.\r
\r
- @param[in] Map The container of TxToken.\r
+ @param[in] Map The container of Tx4Token or Tx6Token.\r
@param[in] Item Current item to check against.\r
@param[in] Context The Token to check againist.\r
\r
//\r
// Transmit the request message.\r
//\r
- Status = HttpTransmitTcp4 (\r
+ Status = HttpTransmitTcp (\r
ValueInItem->HttpInstance,\r
ValueInItem,\r
(UINT8*) RequestStr,\r
/**\r
Receive the HTTP response by processing the associated HTTP token.\r
\r
- @param[in] Map The container of RxToken.\r
+ @param[in] Map The container of Rx4Token or Rx6Token.\r
@param[in] Item Current item to check against.\r
@param[in] Context The Token to check againist.\r
\r
return HttpResponseWorker ((HTTP_TOKEN_WRAP *) Item->Value);\r
}\r
\r
+/**\r
+ Receive the HTTP header by processing the associated HTTP token.\r
+\r
+ @param[in] HttpInstance The HTTP instance private data.\r
+ @param[in, out] SizeofHeaders The HTTP header length.\r
+ @param[in, out] BufferSize The size of buffer to cacahe the header message.\r
+ \r
+ @retval EFI_SUCCESS The HTTP header is received. \r
+ @retval Others Other errors as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpTcpReceiveHeader (\r
+ IN HTTP_PROTOCOL *HttpInstance,\r
+ IN OUT UINTN *SizeofHeaders,\r
+ IN OUT UINTN *BufferSize\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_TCP4_IO_TOKEN *Rx4Token;\r
+ EFI_TCP4_PROTOCOL *Tcp4;\r
+ EFI_TCP6_IO_TOKEN *Rx6Token;\r
+ EFI_TCP6_PROTOCOL *Tcp6;\r
+ CHAR8 **EndofHeader;\r
+ CHAR8 **HttpHeaders;\r
+ CHAR8 *Buffer;\r
+\r
+ ASSERT (HttpInstance != NULL);\r
+\r
+ EndofHeader = HttpInstance->EndofHeader;\r
+ HttpHeaders = HttpInstance->HttpHeaders;\r
+ Tcp4 = HttpInstance->Tcp4;\r
+ Tcp6 = HttpInstance->Tcp6;\r
+ Buffer = NULL;\r
+ Rx4Token = NULL;\r
+ Rx6Token = NULL;\r
+ \r
+ if (HttpInstance->LocalAddressIsIPv6) {\r
+ ASSERT (Tcp6 != NULL);\r
+ } else {\r
+ ASSERT (Tcp4 != NULL);\r
+ }\r
+\r
+ if (!HttpInstance->LocalAddressIsIPv6) {\r
+ Rx4Token = &HttpInstance->Rx4Token;\r
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
+ if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
+ //\r
+ while (*EndofHeader == NULL) { \r
+ HttpInstance->IsRxDone = FALSE;\r
+ Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
+ Status = Tcp4->Receive (Tcp4, Rx4Token);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
+ return Status;\r
+ }\r
+ \r
+ while (!HttpInstance->IsRxDone) {\r
+ Tcp4->Poll (Tcp4);\r
+ } \r
+ \r
+ Status = Rx4Token->CompletionToken.Status;\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Append the response string.\r
+ //\r
+ *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
+ Buffer = AllocateZeroPool (*BufferSize);\r
+ if (Buffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ return Status;\r
+ }\r
+ \r
+ if (*HttpHeaders != NULL) {\r
+ CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));\r
+ FreePool (*HttpHeaders);\r
+ }\r
+ \r
+ CopyMem (\r
+ Buffer + (*SizeofHeaders),\r
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,\r
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength\r
+ );\r
+ *HttpHeaders = Buffer;\r
+ *SizeofHeaders = *BufferSize;\r
+ \r
+ //\r
+ // Check whether we received end of HTTP headers.\r
+ //\r
+ *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR); \r
+ }\r
+ FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+ Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
+ \r
+ } else {\r
+ Rx6Token = &HttpInstance->Rx6Token;\r
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
+ if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ return Status;\r
+ }\r
+ \r
+ //\r
+ // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
+ //\r
+ while (*EndofHeader == NULL) { \r
+ HttpInstance->IsRxDone = FALSE;\r
+ Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
+ Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
+ Status = Tcp6->Receive (Tcp6, Rx6Token);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
+ return Status;\r
+ }\r
+ \r
+ while (!HttpInstance->IsRxDone) {\r
+ Tcp6->Poll (Tcp6);\r
+ } \r
+ \r
+ Status = Rx6Token->CompletionToken.Status;\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r