public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Saloni Kasbekar" <saloni.kasbekar@intel.com>
To: devel@edk2.groups.io
Cc: Saloni Kasbekar <saloni.kasbekar@intel.com>,
	Maciej Rabeda <maciej.rabeda@linux.intel.com>,
	Wu Jiaxin <jiaxin.wu@intel.com>, Siyuan Fu <siyuan.fu@intel.com>
Subject: [edk2-staging/HttpProxy PATCH v3 3/7] NetworkPkg/HttpBootDxe: Update HTTP Boot Driver with parsed Proxy URL
Date: Fri,  2 Dec 2022 11:12:22 -0800	[thread overview]
Message-ID: <40249646b0fd9e44940b3a001589c1d22e53e076.1670008048.git.saloni.kasbekar@intel.com> (raw)
In-Reply-To: <cover.1670008048.git.saloni.kasbekar@intel.com>

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3951

Add ProxyUri to HTTP_BOOT_PRIVATE_DATA
Parse HTTP Boot Device path to process Proxy and EndPoint URLs

Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Saloni Kasbekar <saloni.kasbekar@intel.com>
---
 NetworkPkg/HttpBootDxe/HttpBootClient.c  |  30 ++++-
 NetworkPkg/HttpBootDxe/HttpBootDxe.h     |   6 +
 NetworkPkg/HttpBootDxe/HttpBootImpl.c    |  57 +++++----
 NetworkPkg/HttpBootDxe/HttpBootSupport.c | 154 +++++++++++++++++------
 NetworkPkg/HttpBootDxe/HttpBootSupport.h |  13 +-
 5 files changed, 189 insertions(+), 71 deletions(-)

diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootDxe/HttpBootClient.c
index 40f64fcb6b..b13155b576 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootClient.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c
@@ -678,6 +678,10 @@ HttpBootFreeCache (
         FreePool (Cache->RequestData->Url);
       }
 
+      if (Cache->RequestData->ProxyUrl != NULL) {
+        FreePool (Cache->RequestData->ProxyUrl);
+      }
+
       FreePool (Cache->RequestData);
     }
 
@@ -950,6 +954,7 @@ HttpBootGetBootFile (
   UINT8                    *Block;
   UINTN                    UrlSize;
   CHAR16                   *Url;
+  CHAR16                   *ProxyUrl;
   BOOLEAN                  IdentityMode;
   UINTN                    ReceivedSize;
   CHAR8                    BaseAuthValue[80];
@@ -989,6 +994,22 @@ HttpBootGetBootFile (
   // Not found in cache, try to download it through HTTP.
   //
 
+  //
+  // Initialize ProxyUrl - Set to NULL if connecting without Proxy
+  //
+  if (Private->ProxyUri != NULL) {
+    UrlSize  = AsciiStrSize (Private->ProxyUri);
+    ProxyUrl = AllocatePool (UrlSize * (sizeof (CHAR16)));
+    if (ProxyUrl == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ERROR_1;
+    }
+
+    AsciiStrToUnicodeStrS (Private->ProxyUri, ProxyUrl, UrlSize);
+  } else {
+    ProxyUrl = NULL;
+  }
+
   //
   // 1. Create a temp cache item for the requested URI if caller doesn't provide buffer.
   //
@@ -1106,8 +1127,9 @@ HttpBootGetBootFile (
     goto ERROR_3;
   }
 
-  RequestData->Method = HeaderOnly ? HttpMethodHead : HttpMethodGet;
-  RequestData->Url    = Url;
+  RequestData->Method   = HeaderOnly ? HttpMethodHead : HttpMethodGet;
+  RequestData->Url      = Url;
+  RequestData->ProxyUrl = ProxyUrl;
 
   //
   // 2.3 Record the request info in a temp cache item.
@@ -1441,6 +1463,10 @@ ERROR_2:
   }
 
 ERROR_1:
+  if (ProxyUrl != NULL) {
+    FreePool (ProxyUrl);
+  }
+
   if (Url != NULL) {
     FreePool (Url);
   }
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
index 5ff8ad4698..8caf2e9a45 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
@@ -223,6 +223,12 @@ struct _HTTP_BOOT_PRIVATE_DATA {
   CHAR8                                        *FilePathUri;
   VOID                                         *FilePathUriParser;
 
+  //
+  // URI string for the Proxy host if BootFileUri contains a Proxy
+  // URI in the path
+  //
+  CHAR8                                        *ProxyUri;
+
   //
   // Cached HTTP data
   //
diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
index b4c61925b9..5735b96d9e 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
@@ -115,19 +115,21 @@ HttpBootStart (
 {
   UINTN       Index;
   EFI_STATUS  Status;
-  CHAR8       *Uri;
+  CHAR8       *ProxyUri;
+  CHAR8       *EndPointUri;
 
-  Uri = NULL;
+  ProxyUri    = NULL;
+  EndPointUri = NULL;
 
   if ((Private == NULL) || (FilePath == NULL)) {
     return EFI_INVALID_PARAMETER;
   }
 
   //
-  // Check the URI in the input FilePath, in order to see whether it is
+  // Check the URIs in the input FilePath, in order to see whether it is
   // required to boot from a new specified boot file.
   //
-  Status = HttpBootParseFilePath (FilePath, &Uri);
+  Status = HttpBootParseFilePath (FilePath, &ProxyUri, &EndPointUri);
   if (EFI_ERROR (Status)) {
     return EFI_INVALID_PARAMETER;
   }
@@ -143,28 +145,21 @@ HttpBootStart (
     // recorded before.
     //
     if ((UsingIpv6 != Private->UsingIpv6) ||
-        ((Uri != NULL) && (AsciiStrCmp (Private->BootFileUri, Uri) != 0)))
+        ((EndPointUri != NULL) && (AsciiStrCmp (Private->BootFileUri, EndPointUri) != 0)))
     {
       //
       // Restart is required, first stop then continue this start function.
       //
       Status = HttpBootStop (Private);
       if (EFI_ERROR (Status)) {
-        if (Uri != NULL) {
-          FreePool (Uri);
-        }
-
-        return Status;
+        goto ERROR;
       }
     } else {
       //
       // Restart is not required.
       //
-      if (Uri != NULL) {
-        FreePool (Uri);
-      }
-
-      return EFI_ALREADY_STARTED;
+      Status = EFI_ALREADY_STARTED;
+      goto ERROR;
     }
   }
 
@@ -176,17 +171,16 @@ HttpBootStart (
   } else if (!UsingIpv6 && (Private->Ip4Nic != NULL)) {
     Private->UsingIpv6 = FALSE;
   } else {
-    if (Uri != NULL) {
-      FreePool (Uri);
-    }
-
-    return EFI_UNSUPPORTED;
+    Status = EFI_UNSUPPORTED;
+    goto ERROR;
   }
 
   //
-  // Record the specified URI and prepare the URI parser if needed.
+  // Record the specified URIs and prepare the URI parser if needed.
   //
-  Private->FilePathUri = Uri;
+  Private->ProxyUri    = ProxyUri;
+  Private->FilePathUri = EndPointUri;
+
   if (Private->FilePathUri != NULL) {
     Status = HttpParseUrl (
                Private->FilePathUri,
@@ -195,8 +189,7 @@ HttpBootStart (
                &Private->FilePathUriParser
                );
     if (EFI_ERROR (Status)) {
-      FreePool (Private->FilePathUri);
-      return Status;
+      goto ERROR;
     }
   }
 
@@ -228,6 +221,17 @@ HttpBootStart (
   Print (L"\n>>Start HTTP Boot over IPv%d", Private->UsingIpv6 ? 6 : 4);
 
   return EFI_SUCCESS;
+
+ERROR:
+  if (ProxyUri != NULL) {
+    FreePool (ProxyUri);
+  }
+
+  if (EndPointUri != NULL) {
+    FreePool (EndPointUri);
+  }
+
+  return Status;
 }
 
 /**
@@ -522,6 +526,11 @@ HttpBootStop (
     Private->FilePathUriParser = NULL;
   }
 
+  if (Private->ProxyUri != NULL) {
+    FreePool (Private->ProxyUri);
+    Private->ProxyUri = NULL;
+  }
+
   ZeroMem (Private->OfferBuffer, sizeof (Private->OfferBuffer));
   Private->OfferNum = 0;
   ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.c b/NetworkPkg/HttpBootDxe/HttpBootSupport.c
index 236ef25931..9af6cf0c69 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootSupport.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.c
@@ -551,71 +551,145 @@ HttpBootCheckUriScheme (
   return Status;
 }
 
+/**
+  Get the URI address string from the URI device path node.
+
+  Caller need to free the buffer in the Uri pointer.
+
+  @param[in]   Node               Pointer to the URI device path node.
+  @param[out]  Uri                URI string extracted from the device path.
+
+  @retval EFI_SUCCESS            The URI string is returned.
+  @retval EFI_INVALID_PARAMETER  Parameters are NULL or invalid URI node.
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
+
+**/
+EFI_STATUS
+HttpBootUriFromDevicePath (
+  IN    URI_DEVICE_PATH  *Node,
+  OUT   CHAR8            **Uri
+  )
+{
+  UINTN  UriStrLength;
+
+  if ((Node == NULL) || (Uri == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  UriStrLength = DevicePathNodeLength (Node) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
+
+  if (UriStrLength == 0) {
+    // Invalid URI, return.
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Uri = AllocatePool (UriStrLength + 1);
+  if (*Uri == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  CopyMem (*Uri, Node->Uri, UriStrLength);
+  (*Uri)[UriStrLength] = '\0';
+
+  return EFI_SUCCESS;
+}
+
 /**
   Get the URI address string from the input device path.
 
-  Caller need to free the buffer in the UriAddress pointer.
+  Caller needs to free the buffers returned by this function.
 
-  @param[in]   FilePath         Pointer to the device path which contains a URI device path node.
-  @param[out]  UriAddress       The URI address string extract from the device path.
+  @param[in]   FilePath           Pointer to the device path which contains a URI device path node.
+  @param[out]  ProxyUriAddress    The proxy URI address string extract from the device path (if it exists)
+  @param[out]  EndPointUriAddress The endpoint URI address string for the endpoint host.
 
   @retval EFI_SUCCESS            The URI string is returned.
+  @retval EFI_INVALID_PARAMETER  Parameters are NULL or device path is invalid.
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 
 **/
 EFI_STATUS
 HttpBootParseFilePath (
-  IN     EFI_DEVICE_PATH_PROTOCOL  *FilePath,
-  OUT CHAR8                        **UriAddress
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  OUT CHAR8                     **ProxyUriAddress,
+  OUT CHAR8                     **EndPointUriAddress
   )
 {
-  EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;
-  URI_DEVICE_PATH           *UriDevicePath;
-  CHAR8                     *Uri;
-  UINTN                     UriStrLength;
-
-  if (FilePath == NULL) {
+  EFI_STATUS                Status;
+  EFI_DEVICE_PATH_PROTOCOL  *Node[2];
+  EFI_DEVICE_PATH_PROTOCOL  *TempNode;
+  BOOLEAN                   NodeIsUri[2];
+  UINTN                     Index;
+
+  if ((FilePath == NULL) ||
+      (ProxyUriAddress == NULL) ||
+      (EndPointUriAddress == NULL))
+  {
     return EFI_INVALID_PARAMETER;
   }
 
-  *UriAddress = NULL;
+  *ProxyUriAddress    = NULL;
+  *EndPointUriAddress = NULL;
+  ZeroMem (Node, sizeof (Node));
 
+  // Obtain last 2 device path nodes.
+  // Looking for sequences:
+  // 1) //....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(ProxyServer)/Uri(EndPointServer/FilePath)
+  // 2) //....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]/Uri(EndPointServer/FilePath)
   //
-  // Extract the URI address from the FilePath
-  //
-  TempDevicePath = FilePath;
-  while (!IsDevicePathEnd (TempDevicePath)) {
-    if ((DevicePathType (TempDevicePath) == MESSAGING_DEVICE_PATH) &&
-        (DevicePathSubType (TempDevicePath) == MSG_URI_DP))
-    {
-      UriDevicePath = (URI_DEVICE_PATH *)TempDevicePath;
-      //
-      // UEFI Spec doesn't require the URI to be a NULL-terminated string
-      // So we allocate a new buffer and always append a '\0' to it.
-      //
-      UriStrLength = DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL);
-      if (UriStrLength == 0) {
-        //
-        // return a NULL UriAddress if it's a empty URI device path node.
-        //
-        break;
-      }
-
-      Uri = AllocatePool (UriStrLength + 1);
-      if (Uri == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
+  // Expected:
+  // Node[1] - Uri(EndPointServer/FilePath)
+  // Node[0] - Either Uri(EndPointServer/FilePath) or other.
+  TempNode = FilePath;
+
+  while (!IsDevicePathEnd (TempNode)) {
+    Node[0]  = Node[1];
+    Node[1]  = TempNode;
+    TempNode = NextDevicePathNode (TempNode);
+  }
+
+  // Verify if device path nodes are of type MESSAGING + URI.
+  for (Index = 0; Index < 2; Index++) {
+    if (Node[Index] == NULL) {
+      NodeIsUri[Index] = FALSE;
+    } else {
+      NodeIsUri[Index] = ((DevicePathType (Node[Index]) == MESSAGING_DEVICE_PATH) &&
+                          (DevicePathSubType (Node[Index]) == MSG_URI_DP));
+    }
+  }
 
-      CopyMem (Uri, UriDevicePath->Uri, DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL));
-      Uri[DevicePathNodeLength (UriDevicePath) - sizeof (EFI_DEVICE_PATH_PROTOCOL)] = '\0';
+  // If exists, obtain endpoint URI string.
+  if (NodeIsUri[1]) {
+    Status = HttpBootUriFromDevicePath (
+               (URI_DEVICE_PATH *)Node[1],
+               EndPointUriAddress
+               );
 
-      *UriAddress = Uri;
+    if (EFI_ERROR (Status)) {
+      return Status;
     }
 
-    TempDevicePath = NextDevicePathNode (TempDevicePath);
+    // If exists, obtain proxy URI string.
+    if (NodeIsUri[0]) {
+      Status = HttpBootUriFromDevicePath (
+                 (URI_DEVICE_PATH *)Node[0],
+                 ProxyUriAddress
+                 );
+
+      if (EFI_ERROR (Status)) {
+        goto ErrorExit;
+      }
+    }
   }
 
   return EFI_SUCCESS;
+
+ErrorExit:
+  ASSERT (*EndPointUriAddress != NULL);
+  FreePool (*EndPointUriAddress);
+  *EndPointUriAddress = NULL;
+
+  return Status;
 }
 
 /**
diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.h b/NetworkPkg/HttpBootDxe/HttpBootSupport.h
index 3698e55936..5a46894517 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootSupport.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.h
@@ -136,19 +136,22 @@ HttpBootCheckUriScheme (
 /**
   Get the URI address string from the input device path.
 
-  Caller need to free the buffer in the UriAddress pointer.
+  Caller needs to free the buffers returned by this function.
 
-  @param[in]   FilePath         Pointer to the device path which contains a URI device path node.
-  @param[out]  UriAddress       The URI address string extract from the device path.
+  @param[in]   FilePath           Pointer to the device path which contains a URI device path node.
+  @param[out]  ProxyUriAddress    The proxy URI address string extract from the device path (if it exists)
+  @param[out]  EndPointUriAddress The endpoint URI address string for the endpoint host.
 
   @retval EFI_SUCCESS            The URI string is returned.
+  @retval EFI_INVALID_PARAMETER  Parameters are NULL or device path is invalid.
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate memory.
 
 **/
 EFI_STATUS
 HttpBootParseFilePath (
-  IN     EFI_DEVICE_PATH_PROTOCOL  *FilePath,
-  OUT CHAR8                        **UriAddress
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  OUT CHAR8                     **ProxyUriAddress,
+  OUT CHAR8                     **EndPointUriAddress
   );
 
 /**
-- 
2.36.1.windows.1


  parent reply	other threads:[~2022-12-02 19:12 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-12-02 19:12 [edk2-staging/HttpProxy PATCH v3 0/7] Support HTTPS Proxy Server for HTTP Boot Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 1/7] MdeModulePkg/Library: Support multi-URI HTTP Boot device path Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 2/7] MdePkg/Include: Add Proxy Server URL in EFI_HTTP_REQUEST_DATA Saloni Kasbekar
2022-12-02 19:12 ` Saloni Kasbekar [this message]
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 4/7] NetworkPkg: Add Proxy Support to HTTP_PROTOCOL Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 5/7] NetworkPkg: Add support for HTTP CONNECT Method Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 6/7] NetworkPkg/HttpDxe: Support HTTPS EndPoint server with Proxy Saloni Kasbekar
2022-12-02 19:12 ` [edk2-staging/HttpProxy PATCH v3 7/7] NetworkPkg/HttpBootDxe: Add Proxy URI input in setup menu Saloni Kasbekar

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=40249646b0fd9e44940b3a001589c1d22e53e076.1670008048.git.saloni.kasbekar@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox