/** @file\r
Implementation of the boot file download function.\r
\r
-Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>\r
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<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
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "HttpBootDxe.h"\r
\r
/**\r
- Update the IP and URL device path node to include the boot resource information.\r
+ Update the device path node to include the boot resource information.\r
\r
@param[in] Private The pointer to the driver's private data.\r
\r
@retval EFI_SUCCESS Device patch successfully updated.\r
@retval EFI_OUT_OF_RESOURCES Could not allocate needed resources.\r
@retval Others Unexpected error happened.\r
- \r
+\r
**/\r
EFI_STATUS\r
HttpBootUpdateDevicePath (\r
)\r
{\r
EFI_DEV_PATH *Node;\r
- EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpIpDevicePath;\r
+ EFI_DEVICE_PATH_PROTOCOL *TmpDnsDevicePath;\r
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;\r
UINTN Length;\r
EFI_STATUS Status;\r
\r
- TmpDevicePath = NULL;\r
- \r
+ TmpIpDevicePath = NULL;\r
+ TmpDnsDevicePath = NULL;\r
+\r
//\r
// Update the IP node with DHCP assigned information.\r
//\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.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
+\r
+ TmpIpDevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
FreePool (Node);\r
- if (TmpDevicePath == NULL) {\r
+ if (TmpIpDevicePath == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
+ //\r
+ // Update the DNS node with DNS server IP list if existed.\r
+ //\r
+ if (Private->DnsServerIp != NULL) {\r
+ Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + sizeof (Node->Dns.IsIPv6) + Private->DnsServerCount * sizeof (EFI_IP_ADDRESS);\r
+ Node = AllocatePool (Length);\r
+ if (Node == NULL) {\r
+ FreePool (TmpIpDevicePath);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
+ Node->DevPath.SubType = MSG_DNS_DP;\r
+ SetDevicePathNodeLength (Node, Length);\r
+ Node->Dns.IsIPv6 = Private->UsingIpv6 ? 0x01 : 0x00;\r
+ CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL) + sizeof (Node->Dns.IsIPv6), Private->DnsServerIp, Private->DnsServerCount * sizeof (EFI_IP_ADDRESS));\r
+\r
+ TmpDnsDevicePath = AppendDevicePathNode (TmpIpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
+ FreePool (Node);\r
+ FreePool (TmpIpDevicePath);\r
+ TmpIpDevicePath = NULL;\r
+ if (TmpDnsDevicePath == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ }\r
+\r
//\r
// Update the URI node with the boot file URI.\r
//\r
Length = sizeof (EFI_DEVICE_PATH_PROTOCOL) + AsciiStrSize (Private->BootFileUri);\r
Node = AllocatePool (Length);\r
if (Node == NULL) {\r
- FreePool (TmpDevicePath);\r
+ if (TmpIpDevicePath != NULL) {\r
+ FreePool (TmpIpDevicePath);\r
+ }\r
+ if (TmpDnsDevicePath != NULL) {\r
+ FreePool (TmpDnsDevicePath);\r
+ }\r
return EFI_OUT_OF_RESOURCES;\r
}\r
Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
Node->DevPath.SubType = MSG_URI_DP;\r
SetDevicePathNodeLength (Node, Length);\r
CopyMem ((UINT8*) Node + sizeof (EFI_DEVICE_PATH_PROTOCOL), Private->BootFileUri, AsciiStrSize (Private->BootFileUri));\r
- \r
- NewDevicePath = AppendDevicePathNode (TmpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
+\r
+ if (TmpDnsDevicePath != NULL) {\r
+ NewDevicePath = AppendDevicePathNode (TmpDnsDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
+ FreePool (TmpDnsDevicePath);\r
+ } else {\r
+ ASSERT (TmpIpDevicePath != NULL);\r
+ NewDevicePath = AppendDevicePathNode (TmpIpDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
+ FreePool (TmpIpDevicePath);\r
+ }\r
FreePool (Node);\r
- FreePool (TmpDevicePath);\r
if (NewDevicePath == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
FreePool (Private->Ip4Nic->DevicePath);\r
Private->Ip4Nic->DevicePath = NewDevicePath;\r
} else {\r
FreePool (Private->Ip6Nic->DevicePath);\r
Private->Ip6Nic->DevicePath = NewDevicePath;\r
}\r
- \r
+\r
return EFI_SUCCESS;\r
}\r
\r
HTTP_BOOT_DHCP4_PACKET_CACHE *HttpOffer;\r
UINT32 SelectIndex;\r
UINT32 ProxyIndex;\r
+ UINT32 DnsServerIndex;\r
EFI_DHCP4_PACKET_OPTION *Option;\r
EFI_STATUS Status;\r
\r
SelectIndex = Private->SelectIndex - 1;\r
ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM);\r
\r
+ DnsServerIndex = 0;\r
+\r
Status = EFI_SUCCESS;\r
\r
//\r
//\r
// In Corporate environment, we need a HttpOffer.\r
//\r
- if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) || \r
+ if ((SelectOffer->OfferType == HttpOfferTypeDhcpIpUri) ||\r
(SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns) ||\r
(SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns)) {\r
HttpOffer = SelectOffer;\r
}\r
\r
//\r
- // Configure the default DNS server if server assigned.\r
+ // Check the URI scheme.\r
//\r
- if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || \r
+ Status = HttpBootCheckUriScheme (Private->BootFileUri);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HttpBootDhcp4ExtractUriInfo: %r.\n", Status));\r
+ if (Status == EFI_INVALID_PARAMETER) {\r
+ AsciiPrint ("\n Error: Invalid URI address.\n");\r
+ } else if (Status == EFI_ACCESS_DENIED) {\r
+ AsciiPrint ("\n Error: Access forbidden, only HTTPS connection is allowed.\n");\r
+ }\r
+ return Status;\r
+ }\r
+\r
+ if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) ||\r
(SelectOffer->OfferType == HttpOfferTypeDhcpDns) ||\r
(SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns)) {\r
Option = SelectOffer->OptList[HTTP_BOOT_DHCP4_TAG_INDEX_DNS_SERVER];\r
ASSERT (Option != NULL);\r
+\r
+ //\r
+ // Record the Dns Server address list.\r
+ //\r
+ Private->DnsServerCount = (Option->Length) / sizeof (EFI_IPv4_ADDRESS);\r
+\r
+ Private->DnsServerIp = AllocateZeroPool (Private->DnsServerCount * sizeof (EFI_IP_ADDRESS));\r
+ if (Private->DnsServerIp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (DnsServerIndex = 0; DnsServerIndex < Private->DnsServerCount; DnsServerIndex++) {\r
+ CopyMem (&(Private->DnsServerIp[DnsServerIndex].v4), &(((EFI_IPv4_ADDRESS *) Option->Data)[DnsServerIndex]), sizeof (EFI_IPv4_ADDRESS));\r
+ }\r
+\r
+ //\r
+ // Configure the default DNS server if server assigned.\r
+ //\r
Status = HttpBootRegisterIp4Dns (\r
Private,\r
Option->Length,\r
Option->Data\r
);\r
if (EFI_ERROR (Status)) {\r
+ FreePool (Private->DnsServerIp);\r
+ Private->DnsServerIp = NULL;\r
return Status;\r
}\r
}\r
if (EFI_ERROR (Status) || Private->Port == 0) {\r
Private->Port = 80;\r
}\r
- \r
+\r
//\r
// All boot informations are valid here.\r
//\r
- AsciiPrint ("\n URI: %a", Private->BootFileUri);\r
\r
//\r
- // Update the device path to include the IP and boot URI information.\r
+ // Update the device path to include the boot resource information.\r
//\r
Status = HttpBootUpdateDevicePath (Private);\r
+ if (EFI_ERROR (Status) && Private->DnsServerIp != NULL) {\r
+ FreePool (Private->DnsServerIp);\r
+ Private->DnsServerIp = NULL;\r
+ }\r
\r
return Status;\r
}\r
HTTP_BOOT_DHCP6_PACKET_CACHE *HttpOffer;\r
UINT32 SelectIndex;\r
UINT32 ProxyIndex;\r
+ UINT32 DnsServerIndex;\r
EFI_DHCP6_PACKET_OPTION *Option;\r
EFI_IPv6_ADDRESS IpAddr;\r
CHAR8 *HostName;\r
+ UINTN HostNameSize;\r
CHAR16 *HostNameStr;\r
EFI_STATUS Status;\r
\r
SelectIndex = Private->SelectIndex - 1;\r
ASSERT (SelectIndex < HTTP_BOOT_OFFER_MAX_NUM);\r
\r
+ DnsServerIndex = 0;\r
+\r
Status = EFI_SUCCESS;\r
HostName = NULL;\r
//\r
Private->BootFileUri = Private->FilePathUri;\r
}\r
\r
+ //\r
+ // Check the URI scheme.\r
+ //\r
+ Status = HttpBootCheckUriScheme (Private->BootFileUri);\r
+ if (EFI_ERROR (Status)) {\r
+ DEBUG ((EFI_D_ERROR, "HttpBootDhcp6ExtractUriInfo: %r.\n", Status));\r
+ if (Status == EFI_INVALID_PARAMETER) {\r
+ AsciiPrint ("\n Error: Invalid URI address.\n");\r
+ } else if (Status == EFI_ACCESS_DENIED) {\r
+ AsciiPrint ("\n Error: Access forbidden, only HTTPS connection is allowed.\n");\r
+ }\r
+ return Status;\r
+ }\r
+\r
//\r
// Set the Local station address to IP layer.\r
//\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
- \r
+\r
//\r
- // Configure the default DNS server if server assigned.\r
+ // Register the IPv6 gateway address to the network device.\r
//\r
- if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) || \r
+ Status = HttpBootSetIp6Gateway (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ if ((SelectOffer->OfferType == HttpOfferTypeDhcpNameUriDns) ||\r
(SelectOffer->OfferType == HttpOfferTypeDhcpDns) ||\r
(SelectOffer->OfferType == HttpOfferTypeDhcpIpUriDns)) {\r
Option = SelectOffer->OptList[HTTP_BOOT_DHCP6_IDX_DNS_SERVER];\r
ASSERT (Option != NULL);\r
+\r
+ //\r
+ // Record the Dns Server address list.\r
+ //\r
+ Private->DnsServerCount = HTONS (Option->OpLen) / sizeof (EFI_IPv6_ADDRESS);\r
+\r
+ Private->DnsServerIp = AllocateZeroPool (Private->DnsServerCount * sizeof (EFI_IP_ADDRESS));\r
+ if (Private->DnsServerIp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ for (DnsServerIndex = 0; DnsServerIndex < Private->DnsServerCount; DnsServerIndex++) {\r
+ CopyMem (&(Private->DnsServerIp[DnsServerIndex].v6), &(((EFI_IPv6_ADDRESS *) Option->Data)[DnsServerIndex]), sizeof (EFI_IPv6_ADDRESS));\r
+ }\r
+\r
+ //\r
+ // Configure the default DNS server if server assigned.\r
+ //\r
Status = HttpBootSetIp6Dns (\r
Private,\r
HTONS (Option->OpLen),\r
Option->Data\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Error;\r
}\r
}\r
- \r
+\r
//\r
- // Extract the HTTP server Ip frome URL. This is used to Check route table \r
+ // Extract the HTTP server Ip from 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
Private->BootFileUriParser,\r
&IpAddr\r
);\r
- \r
+\r
if (EFI_ERROR (Status)) {\r
//\r
// The Http server address is expressed by Name Ip, so perform DNS resolution\r
&HostName\r
);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto Error;\r
}\r
- \r
- HostNameStr = AllocateZeroPool ((AsciiStrLen (HostName) + 1) * sizeof (CHAR16));\r
+\r
+ HostNameSize = AsciiStrSize (HostName);\r
+ HostNameStr = AllocateZeroPool (HostNameSize * sizeof (CHAR16));\r
if (HostNameStr == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto Error;\r
}\r
- \r
- AsciiStrToUnicodeStr (HostName, HostNameStr);\r
+\r
+ AsciiStrToUnicodeStrS (HostName, HostNameStr, HostNameSize);\r
+\r
+ if (HostName != NULL) {\r
+ FreePool (HostName);\r
+ }\r
+\r
Status = HttpBootDns (Private, HostNameStr, &IpAddr);\r
FreePool (HostNameStr);\r
if (EFI_ERROR (Status)) {\r
+ AsciiPrint ("\n Error: Could not retrieve the host address from DNS server.\n");\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
+\r
+ CopyMem (&Private->ServerIp.v6, &IpAddr, sizeof (EFI_IPv6_ADDRESS));\r
+\r
//\r
// Extract the port from URL, and use default HTTP port 80 if not provided.\r
//\r
if (EFI_ERROR (Status) || Private->Port == 0) {\r
Private->Port = 80;\r
}\r
- \r
+\r
//\r
// All boot informations are valid here.\r
//\r
- AsciiPrint ("\n URI: %a", Private->BootFileUri);\r
+\r
//\r
- // Update the device path to include the IP and boot URI information.\r
+ // Update the device path to include the boot resource information.\r
//\r
Status = HttpBootUpdateDevicePath (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ goto Error;\r
+ }\r
+\r
+ return Status;\r
\r
Error:\r
- \r
- if (HostName != NULL) {\r
- FreePool (HostName);\r
+ if (Private->DnsServerIp != NULL) {\r
+ FreePool (Private->DnsServerIp);\r
+ Private->DnsServerIp = NULL;\r
}\r
- \r
+\r
return Status;\r
}\r
\r
)\r
{\r
EFI_STATUS Status;\r
- \r
+\r
//\r
// Start D.O.R.A/S.A.R.R exchange to acquire station ip address and\r
// other Http boot information.\r
return Status;\r
}\r
\r
+/**\r
+ HttpIo Callback function which will be invoked when specified HTTP_IO_CALLBACK_EVENT happened.\r
+\r
+ @param[in] EventType Indicate the Event type that occurs in the current callback.\r
+ @param[in] Message HTTP message which will be send to, or just received from HTTP server.\r
+ @param[in] Context The Callback Context pointer.\r
+\r
+ @retval EFI_SUCCESS Tells the HttpIo to continue the HTTP process.\r
+ @retval Others Tells the HttpIo to abort the current HTTP process.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpBootHttpIoCallback (\r
+ IN HTTP_IO_CALLBACK_EVENT EventType,\r
+ IN EFI_HTTP_MESSAGE *Message,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ HTTP_BOOT_PRIVATE_DATA *Private;\r
+ EFI_STATUS Status;\r
+ Private = (HTTP_BOOT_PRIVATE_DATA *) Context;\r
+ if (Private->HttpBootCallback != NULL) {\r
+ Status = Private->HttpBootCallback->Callback (\r
+ Private->HttpBootCallback,\r
+ EventType == HttpIoRequest ? HttpBootHttpRequest : HttpBootHttpResponse,\r
+ EventType == HttpIoRequest ? FALSE : TRUE,\r
+ sizeof (EFI_HTTP_MESSAGE),\r
+ (VOID *) Message\r
+ );\r
+ return Status;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
/**\r
Create a HttpIo instance for the file download.\r
\r
HTTP_IO_CONFIG_DATA ConfigData;\r
EFI_STATUS Status;\r
EFI_HANDLE ImageHandle;\r
+ UINT32 TimeoutValue;\r
\r
ASSERT (Private != NULL);\r
\r
+ //\r
+ // Get HTTP timeout value\r
+ //\r
+ TimeoutValue = PcdGet32 (PcdHttpIoTimeout);\r
+\r
ZeroMem (&ConfigData, sizeof (HTTP_IO_CONFIG_DATA));\r
if (!Private->UsingIpv6) {\r
ConfigData.Config4.HttpVersion = HttpVersion11;\r
- ConfigData.Config4.RequestTimeOut = HTTP_BOOT_REQUEST_TIMEOUT;\r
+ ConfigData.Config4.RequestTimeOut = TimeoutValue;\r
IP4_COPY_ADDRESS (&ConfigData.Config4.LocalIp, &Private->StationIp.v4);\r
IP4_COPY_ADDRESS (&ConfigData.Config4.SubnetMask, &Private->SubnetMask.v4);\r
ImageHandle = Private->Ip4Nic->ImageHandle;\r
} else {\r
ConfigData.Config6.HttpVersion = HttpVersion11;\r
- ConfigData.Config6.RequestTimeOut = HTTP_BOOT_REQUEST_TIMEOUT;\r
+ ConfigData.Config6.RequestTimeOut = TimeoutValue;\r
IP6_COPY_ADDRESS (&ConfigData.Config6.LocalIp, &Private->StationIp.v6);\r
ImageHandle = Private->Ip6Nic->ImageHandle;\r
}\r
Private->Controller,\r
Private->UsingIpv6 ? IP_VERSION_6 : IP_VERSION_4,\r
&ConfigData,\r
+ HttpBootHttpIoCallback,\r
+ (VOID *) Private,\r
&Private->HttpIo\r
);\r
if (EFI_ERROR (Status)) {\r
LIST_ENTRY *Entry;\r
LIST_ENTRY *NextEntry;\r
HTTP_BOOT_CACHE_CONTENT *Cache;\r
- \r
+\r
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->CacheList) {\r
Cache = NET_LIST_USER_STRUCT (Entry, HTTP_BOOT_CACHE_CONTENT, Link);\r
RemoveEntryList (&Cache->Link);\r
HTTP_BOOT_CACHE_CONTENT *Cache;\r
HTTP_BOOT_ENTITY_DATA *EntityData;\r
UINTN CopyedSize;\r
- \r
- if (Uri == NULL || BufferSize == 0 || Buffer == NULL || ImageType == NULL) {\r
+\r
+ if (Uri == NULL || BufferSize == NULL || Buffer == NULL || ImageType == NULL) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
//\r
if ((Cache->RequestData != NULL) &&\r
(Cache->RequestData->Url != NULL) &&\r
- (StrCmp (Uri, Cache->RequestData->Url) == 0)) \r
- {\r
+ (StrCmp (Uri, Cache->RequestData->Url) == 0)) {\r
//\r
// Hit in cache, record image type.\r
//\r
\r
@retval EFI_SUCCESS Continue to parser the message body.\r
@retval Others Abort the parse.\r
- \r
+\r
**/\r
EFI_STATUS\r
EFIAPI\r
{\r
HTTP_BOOT_CALLBACK_DATA *CallbackData;\r
HTTP_BOOT_ENTITY_DATA *NewEntityData;\r
+ EFI_STATUS Status;\r
+ EFI_HTTP_BOOT_CALLBACK_PROTOCOL *HttpBootCallback;\r
\r
//\r
// We only care about the entity data.\r
}\r
\r
CallbackData = (HTTP_BOOT_CALLBACK_DATA *) Context;\r
+ HttpBootCallback = CallbackData->Private->HttpBootCallback;\r
+ if (HttpBootCallback != NULL) {\r
+ Status = HttpBootCallback->Callback (\r
+ HttpBootCallback,\r
+ HttpBootHttpEntityBody,\r
+ TRUE,\r
+ (UINT32)Length,\r
+ Data\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
//\r
// Copy data if caller has provided a buffer.\r
//\r
\r
/**\r
This function download the boot file by using UEFI HTTP protocol.\r
- \r
+\r
@param[in] Private The pointer to the driver's private data.\r
@param[in] HeaderOnly Only request the response header, it could save a lot of time if\r
the caller only want to know the size of the requested file.\r
UINTN ContentLength;\r
HTTP_BOOT_CACHE_CONTENT *Cache;\r
UINT8 *Block;\r
+ UINTN UrlSize;\r
CHAR16 *Url;\r
BOOLEAN IdentityMode;\r
UINTN ReceivedSize;\r
- \r
+\r
ASSERT (Private != NULL);\r
ASSERT (Private->HttpCreated);\r
\r
//\r
// First, check whether we already cached the requested Uri.\r
//\r
- Url = AllocatePool ((AsciiStrLen (Private->BootFileUri) + 1) * sizeof (CHAR16));\r
+ UrlSize = AsciiStrSize (Private->BootFileUri);\r
+ Url = AllocatePool (UrlSize * sizeof (CHAR16));\r
if (Url == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
- AsciiStrToUnicodeStr (Private->BootFileUri, Url);\r
- if (!HeaderOnly) {\r
+ AsciiStrToUnicodeStrS (Private->BootFileUri, Url, UrlSize);\r
+ if (!HeaderOnly && Buffer != NULL) {\r
Status = HttpBootGetFileFromCache (Private, Url, BufferSize, Buffer, ImageType);\r
if (Status != EFI_NOT_FOUND) {\r
FreePool (Url);\r
// Accept\r
// User-Agent\r
//\r
- HttpIoHeader = HttpBootCreateHeader (3);\r
+ HttpIoHeader = HttpIoCreateHeader (3);\r
if (HttpIoHeader == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
goto ERROR_2;\r
if (EFI_ERROR (Status)) {\r
goto ERROR_3;\r
}\r
- Status = HttpBootSetHeader (\r
+ Status = HttpIoSetHeader (\r
HttpIoHeader,\r
HTTP_HEADER_HOST,\r
HostName\r
//\r
// Add HTTP header field 2: Accept\r
//\r
- Status = HttpBootSetHeader (\r
+ Status = HttpIoSetHeader (\r
HttpIoHeader,\r
HTTP_HEADER_ACCEPT,\r
"*/*"\r
//\r
// Add HTTP header field 3: User-Agent\r
//\r
- Status = HttpBootSetHeader (\r
+ Status = HttpIoSetHeader (\r
HttpIoHeader,\r
HTTP_HEADER_USER_AGENT,\r
HTTP_USER_AGENT_EFI_HTTP_BOOT\r
}\r
RequestData->Method = HeaderOnly ? HttpMethodHead : HttpMethodGet;\r
RequestData->Url = Url;\r
- if (RequestData->Url == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ERROR_4;\r
- }\r
- AsciiStrToUnicodeStr (Private->BootFileUri, RequestData->Url);\r
\r
//\r
// 2.3 Record the request info in a temp cache item.\r
Cache->ResponseData = ResponseData;\r
Cache->ImageType = *ImageType;\r
}\r
- \r
+\r
//\r
// 3.3 Init a message-body parser from the header information.\r
//\r
Context.Buffer = Buffer;\r
Context.BufferSize = *BufferSize;\r
Context.Cache = Cache;\r
+ Context.Private = Private;\r
Status = HttpInitMsgParser (\r
- HeaderOnly? HttpMethodHead : HttpMethodGet,\r
+ HeaderOnly ? HttpMethodHead : HttpMethodGet,\r
ResponseData->Response.StatusCode,\r
ResponseData->HeaderCount,\r
ResponseData->Headers,\r
FALSE,\r
&ResponseBody\r
);\r
- if (EFI_ERROR (Status)) {\r
+ if (EFI_ERROR (Status) || EFI_ERROR (ResponseBody.Status)) {\r
+ if (EFI_ERROR (ResponseBody.Status)) {\r
+ Status = ResponseBody.Status;\r
+ }\r
goto ERROR_6;\r
}\r
ReceivedSize += ResponseBody.BodyLength;\r
+ if (Private->HttpBootCallback != NULL) {\r
+ Status = Private->HttpBootCallback->Callback (\r
+ Private->HttpBootCallback,\r
+ HttpBootHttpEntityBody,\r
+ TRUE,\r
+ (UINT32)ResponseBody.BodyLength,\r
+ ResponseBody.Body\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ERROR_6;\r
+ }\r
+ }\r
}\r
} else {\r
//\r
FALSE,\r
&ResponseBody\r
);\r
- if (EFI_ERROR (Status)) {\r
+ if (EFI_ERROR (Status) || EFI_ERROR (ResponseBody.Status)) {\r
+ if (EFI_ERROR (ResponseBody.Status)) {\r
+ Status = ResponseBody.Status;\r
+ }\r
goto ERROR_6;\r
}\r
\r
\r
if (*BufferSize < ContentLength) {\r
Status = EFI_BUFFER_TOO_SMALL;\r
+ } else {\r
+ Status = EFI_SUCCESS;\r
}\r
*BufferSize = ContentLength;\r
\r
HttpFreeMsgParser (Parser);\r
}\r
\r
- return EFI_SUCCESS;\r
- \r
+ return Status;\r
+\r
ERROR_6:\r
if (Parser != NULL) {\r
HttpFreeMsgParser (Parser);\r
FreePool (Context.Block);\r
}\r
HttpBootFreeCache (Cache);\r
- \r
+\r
ERROR_5:\r
if (ResponseData != NULL) {\r
FreePool (ResponseData);\r
FreePool (RequestData);\r
}\r
ERROR_3:\r
- HttpBootFreeHeader (HttpIoHeader);\r
+ HttpIoFreeHeader (HttpIoHeader);\r
ERROR_2:\r
if (Cache != NULL) {\r
FreePool (Cache);\r