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
\r
CallbackData = (HTTP_BOOT_CALLBACK_DATA *) Context;\r
-\r
- //\r
- // Save the data into cache list.\r
- //\r
- NewEntityData = AllocatePool (sizeof (HTTP_BOOT_ENTITY_DATA));\r
- if (NewEntityData == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- if (CallbackData->NewBlock) {\r
- NewEntityData->Block = CallbackData->Block;\r
- CallbackData->Block = NULL;\r
- }\r
- NewEntityData->DataLength = Length;\r
- NewEntityData->DataStart = (UINT8*) Data;\r
- InsertTailList (&CallbackData->Cache->EntityDataList, &NewEntityData->Link);\r
-\r
//\r
// Copy data if caller has provided a buffer.\r
//\r
CallbackData->CopyedSize += MIN (Length, CallbackData->BufferSize - CallbackData->CopyedSize);\r
}\r
\r
+ //\r
+ // The caller doesn't provide a buffer, save the block into cache list.\r
+ //\r
+ if (CallbackData->Cache != NULL) {\r
+ NewEntityData = AllocatePool (sizeof (HTTP_BOOT_ENTITY_DATA));\r
+ if (NewEntityData == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ if (CallbackData->NewBlock) {\r
+ NewEntityData->Block = CallbackData->Block;\r
+ CallbackData->Block = NULL;\r
+ }\r
+ NewEntityData->DataLength = Length;\r
+ NewEntityData->DataStart = (UINT8*) Data;\r
+ InsertTailList (&CallbackData->Cache->EntityDataList, &NewEntityData->Link);\r
+ }\r
return EFI_SUCCESS;\r
}\r
\r
//\r
\r
//\r
- // 1. Create a temp cache item for the requested URI.\r
+ // 1. Create a temp cache item for the requested URI if caller doesn't provide buffer.\r
//\r
Cache = NULL;\r
- if (!HeaderOnly) {\r
+ if ((!HeaderOnly) && (*BufferSize == 0)) {\r
Cache = AllocateZeroPool (sizeof (HTTP_BOOT_CACHE_CONTENT));\r
if (Cache == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
//\r
// 2.3 Record the request info in a temp cache item.\r
//\r
- if (!HeaderOnly) {\r
+ if (Cache != NULL) {\r
Cache->RequestData = RequestData;\r
}\r
\r
//\r
// 3.2 Cache the response header.\r
//\r
- if (!HeaderOnly) {\r
+ if (Cache != NULL) {\r
Cache->ResponseData = ResponseData;\r
}\r
\r
//\r
// 3.4 Continue to receive and parse message-body if needed.\r
//\r
+ Block = NULL;\r
if (!HeaderOnly) {\r
ZeroMem (&ResponseBody, sizeof (HTTP_IO_RESOPNSE_DATA));\r
while (!HttpIsMessageComplete (Parser)) {\r
//\r
- // Allocate a new block to hold the message-body.\r
+ // Allocate a block to hold the message-body, if caller doesn't provide\r
+ // a buffer, the block will be cached and we will allocate a new one here.\r
//\r
- Block = AllocatePool (HTTP_BOOT_BLOCK_SIZE);\r
- if (Block == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ERROR_6;\r
+ if (Block == NULL || Context.BufferSize == 0) {\r
+ Block = AllocatePool (HTTP_BOOT_BLOCK_SIZE);\r
+ if (Block == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ERROR_6;\r
+ }\r
+ Context.NewBlock = TRUE;\r
+ Context.Block = Block;\r
+ } else {\r
+ Context.NewBlock = FALSE;\r
}\r
+\r
ResponseBody.Body = (CHAR8*) Block;\r
ResponseBody.BodyLength = HTTP_BOOT_BLOCK_SIZE;\r
Status = HttpIoRecvResponse (\r
//\r
// Parse the new received block of the message-body, the block will be saved in cache.\r
//\r
- Context.NewBlock = TRUE;\r
- Context.Block = Block;\r
Status = HttpParseMessageBody (\r
Parser,\r
ResponseBody.BodyLength,\r
//\r
// 4. Save the cache item to driver's cache list and return.\r
//\r
- if (!HeaderOnly) {\r
+ if (Cache != NULL) {\r
Cache->EntityLength = ContentLength;\r
InsertTailList (&Private->CacheList, &Cache->Link);\r
}\r