From nobody Mon May 13 15:05:41 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+94092+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94092+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1663797128; cv=none; d=zohomail.com; s=zohoarc; b=V5a7lLbUx/V5FOhMEdcDXHrlIRTMhwNSTzs0yWJWzFBGMl/1Tbq0EHogxMjmQSzViQLlTaGQDJjCK1GRvCCng6zQ0yZnL4NRnlaeR23PQ7hqQWwMrxZxvvlPQgHGK7ZeyKiZaiGDRRG5s9XQsQ6GbDYFoMwMzPiuyYAHWTcsp5w= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1663797128; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=/jtWKTPMYHYMMbRTwpAnm1dmR5y/je7WZj2I9mBJbr4=; b=eSKNOBHYAiA4i4tWoy3pT+FfMqd9gQVqJoRU+BKr3+pxuHJXi9yMsVQW9H49Bvmf1MqPdaXhJES+ixxJ11w4T3toFEQ4XM7LG+oGpyuKC1Xqd7YGb8xLj4Jhye4UglfzO1muDSm5f1/wdpxDoHEFbYbVHIOVA+uJs8e0NZl5mZo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94092+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1663797128741951.7479006652601; Wed, 21 Sep 2022 14:52:08 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id AhvrYY1788612x76YBfmQxDB; Wed, 21 Sep 2022 14:52:08 -0700 X-Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mx.groups.io with SMTP id smtpd.web08.392.1663797121780520189 for ; Wed, 21 Sep 2022 14:52:07 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10477"; a="298850832" X-IronPort-AV: E=Sophos;i="5.93,334,1654585200"; d="scan'208";a="298850832" X-Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2022 14:52:07 -0700 X-IronPort-AV: E=Sophos;i="5.93,334,1654585200"; d="scan'208";a="597172825" X-Received: from fmbiosdev02.amr.corp.intel.com ([10.80.127.10]) by orsmga006-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 21 Sep 2022 14:52:06 -0700 From: "Saloni Kasbekar" To: devel@edk2.groups.io Cc: Saloni Kasbekar , Maciej Rabeda , Wu Jiaxin , Siyuan Fu Subject: [edk2-devel] [[edk2-staging/HttpProxy] 3/3] NetworkPkg/HttpBootDxe: Add Support for HTTPS Proxy Server for HTTP Boot Date: Wed, 21 Sep 2022 14:51:51 -0700 Message-Id: <7bec1a6b3b394ebafdd757cb189b7098e5bf7afa.1663795390.git.saloni.kasbekar@intel.com> In-Reply-To: References: MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,saloni.kasbekar@intel.com X-Gm-Message-State: XjuYvxFv3wAhXjR2AqaHW8B8x1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1663797128; bh=fq+y/7I5vDXwBN7rK3r5krLaSfBnup7KRpaWBZddrp0=; h=Cc:Date:From:Reply-To:Subject:To; b=iXKNEX9FSop0SqGvAFp5h1xUsCvHRNRkIYDPl6Z9fL40UN2e9eL+tzFYbedejLlL2Hu bRq48JkvRXtOZHm+ZYGr7zeb64AKOvdYsB165X3PqCzD1POwkdiOqZnyz9KPMbEJFpWCB AhtuxLkh4pCFj7o+Tw+G5FpIqywxOk6JTEM= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1663797129689100008 Content-Type: text/plain; charset="utf-8" Add CONNECT HTTP command to create a tunnel from Proxy to EndPoint Server. Process the multi-URI device path in the input FilePath. Cc: Maciej Rabeda Cc: Wu Jiaxin Cc: Siyuan Fu Signed-off-by: Saloni Kasbekar --- NetworkPkg/HttpBootDxe/HttpBootClient.c | 211 ++++++++++++++++- NetworkPkg/HttpBootDxe/HttpBootClient.h | 15 ++ NetworkPkg/HttpBootDxe/HttpBootDxe.h | 6 + NetworkPkg/HttpBootDxe/HttpBootImpl.c | 262 ++++++++++++++++----- NetworkPkg/HttpBootDxe/HttpBootImpl.h | 8 + NetworkPkg/HttpBootDxe/HttpBootSupport.c | 24 +- NetworkPkg/HttpBootDxe/HttpBootSupport.h | 8 +- NetworkPkg/HttpDxe/HttpDriver.h | 2 + NetworkPkg/HttpDxe/HttpDxe.inf | 1 + NetworkPkg/HttpDxe/HttpImpl.c | 139 +++++++++-- NetworkPkg/HttpDxe/HttpProto.c | 41 ++-- NetworkPkg/HttpDxe/HttpProto.h | 14 +- NetworkPkg/HttpDxe/HttpsSupport.c | 14 +- NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c | 5 + 14 files changed, 642 insertions(+), 108 deletions(-) diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.c b/NetworkPkg/HttpBootD= xe/HttpBootClient.c index 40f64fcb6b..bfad4809de 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.c +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.c @@ -678,6 +678,10 @@ HttpBootFreeCache ( FreePool (Cache->RequestData->Url); } =20 + if (Cache->RequestData->EndPointUrl !=3D NULL) { + FreePool (Cache->RequestData->EndPointUrl); + } + FreePool (Cache->RequestData); } =20 @@ -901,6 +905,189 @@ HttpBootGetBootFileCallback ( return EFI_SUCCESS; } =20 +/** + This function establishes a connection through a proxy server + + @param[in] Private The pointer to the driver's private dat= a. + + @retval EFI_SUCCESS Connection successful. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources + @retval Others Unexpected error happened. + +**/ +EFI_STATUS +HttpBootConnectProxy ( + IN HTTP_BOOT_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + EFI_HTTP_STATUS_CODE StatusCode; + CHAR8 *HostName; + EFI_HTTP_REQUEST_DATA *RequestData; + HTTP_IO_RESPONSE_DATA *ResponseData; + HTTP_IO *HttpIo; + HTTP_IO_HEADER *HttpIoHeader; + CHAR16 *Url; + CHAR16 *EndPointUrl; + UINTN UrlSize; + VOID *UrlParser; + + Url =3D NULL; + EndPointUrl =3D NULL; + RequestData =3D NULL; + ResponseData =3D NULL; + HttpIoHeader =3D NULL; + + UrlSize =3D AsciiStrSize (Private->BootFileUri); + Url =3D AllocatePool (UrlSize * sizeof (CHAR16)); + if (Url =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + AsciiStrToUnicodeStrS (Private->BootFileUri, Url, UrlSize); + + UrlSize =3D AsciiStrSize (Private->EndPointUri); + EndPointUrl =3D AllocatePool (UrlSize * (sizeof (CHAR16))); + if (EndPointUrl =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + AsciiStrToUnicodeStrS (Private->EndPointUri, EndPointUrl, UrlSize); + + // + // Send HTTP request message. + // + + // + // Build HTTP header for the request, 2 headers are needed to send a CON= NECT method: + // Host + // User + // + HttpIoHeader =3D HttpIoCreateHeader (2); + if (HttpIoHeader =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Add HTTP header field 1: Host (EndPoint URI) + // + Status =3D HttpParseUrl (Private->EndPointUri, (UINT32)AsciiStrLen (Priv= ate->EndPointUri), FALSE, &UrlParser); + if (EFI_ERROR (Status)) { + goto ERROR; + } + + Status =3D HttpUrlGetHostName ( + Private->EndPointUri, + UrlParser, + &HostName + ); + if (EFI_ERROR (Status)) { + goto ERROR; + } + + Status =3D HttpIoSetHeader ( + HttpIoHeader, + HTTP_HEADER_HOST, + HostName + ); + if (EFI_ERROR (Status)) { + goto ERROR; + } + + // + // Add HTTP header field 2: User-Agent + // + Status =3D HttpIoSetHeader ( + HttpIoHeader, + HTTP_HEADER_USER_AGENT, + HTTP_USER_AGENT_EFI_HTTP_BOOT + ); + if (EFI_ERROR (Status)) { + goto ERROR; + } + + // + // Build the rest of HTTP request info. + // + RequestData =3D AllocatePool (sizeof (EFI_HTTP_REQUEST_DATA)); + if (RequestData =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + RequestData->Method =3D HttpMethodConnect; + RequestData->Url =3D Url; + RequestData->EndPointUrl =3D EndPointUrl; + + // + // Send out the request to HTTP server. + // + HttpIo =3D &Private->HttpIo; + Status =3D HttpIoSendRequest ( + HttpIo, + RequestData, + HttpIoHeader->HeaderCount, + HttpIoHeader->Headers, + 0, + NULL + ); + if (EFI_ERROR (Status)) { + goto ERROR; + } + + // + // Receive HTTP response message. + // + + // + // Use zero BodyLength to only receive the response headers. + // + ResponseData =3D AllocateZeroPool (sizeof (HTTP_IO_RESPONSE_DATA)); + if (ResponseData =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + Status =3D HttpIoRecvResponse ( + &Private->HttpIo, + TRUE, + ResponseData + ); + + if (EFI_ERROR (Status) || EFI_ERROR (ResponseData->Status)) { + if (EFI_ERROR (ResponseData->Status)) { + StatusCode =3D HttpIo->RspToken.Message->Data.Response->StatusCode; + HttpBootPrintErrorMessage (StatusCode); + Status =3D ResponseData->Status; + } + + goto ERROR; + } + +ERROR: + if (ResponseData !=3D NULL) { + FreePool (ResponseData); + } + + if (RequestData !=3D NULL) { + FreePool (RequestData); + } + + HttpIoFreeHeader (HttpIoHeader); + + if (EndPointUrl !=3D NULL) { + FreePool (EndPointUrl); + } + + if (Url !=3D NULL) { + FreePool (Url); + } + + return Status; +} + /** This function download the boot file by using UEFI HTTP protocol. =20 @@ -950,6 +1137,7 @@ HttpBootGetBootFile ( UINT8 *Block; UINTN UrlSize; CHAR16 *Url; + CHAR16 *EndPointUrl; BOOLEAN IdentityMode; UINTN ReceivedSize; CHAR8 BaseAuthValue[80]; @@ -977,6 +1165,20 @@ HttpBootGetBootFile ( } =20 AsciiStrToUnicodeStrS (Private->BootFileUri, Url, UrlSize); + + if (Private->EndPointUri !=3D NULL) { + UrlSize =3D AsciiStrSize (Private->EndPointUri); + EndPointUrl =3D AllocatePool (UrlSize * (sizeof (CHAR16))); + if (EndPointUrl =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR_1; + } + + AsciiStrToUnicodeStrS (Private->EndPointUri, EndPointUrl, UrlSize); + } else { + EndPointUrl =3D NULL; + } + if (!HeaderOnly && (Buffer !=3D NULL)) { Status =3D HttpBootGetFileFromCache (Private, Url, BufferSize, Buffer,= ImageType); if (Status !=3D EFI_NOT_FOUND) { @@ -1106,8 +1308,9 @@ HttpBootGetBootFile ( goto ERROR_3; } =20 - RequestData->Method =3D HeaderOnly ? HttpMethodHead : HttpMethodGet; - RequestData->Url =3D Url; + RequestData->Method =3D HeaderOnly ? HttpMethodHead : HttpMethodGet; + RequestData->Url =3D Url; + RequestData->EndPointUrl =3D EndPointUrl; =20 // // 2.3 Record the request info in a temp cache item. @@ -1441,6 +1644,10 @@ ERROR_2: } =20 ERROR_1: + if (EndPointUrl !=3D NULL) { + FreePool (EndPointUrl); + } + if (Url !=3D NULL) { FreePool (Url); } diff --git a/NetworkPkg/HttpBootDxe/HttpBootClient.h b/NetworkPkg/HttpBootD= xe/HttpBootClient.h index 2fba713679..fcd624f536 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootClient.h +++ b/NetworkPkg/HttpBootDxe/HttpBootClient.h @@ -86,6 +86,21 @@ HttpBootCreateHttpIo ( IN HTTP_BOOT_PRIVATE_DATA *Private ); =20 +/** + This function establishes a connection through a proxy server + + @param[in] Private The pointer to the driver's private dat= a. + + @retval EFI_SUCCESS Connection successful. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources + @retval Others Unexpected error happened. + +**/ +EFI_STATUS +HttpBootConnectProxy ( + IN HTTP_BOOT_PRIVATE_DATA *Private + ); + /** This function download the boot file by using UEFI HTTP protocol. =20 diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h b/NetworkPkg/HttpBootDxe/= HttpBootDxe.h index 5ff8ad4698..e2eb1ffc45 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h +++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h @@ -223,6 +223,12 @@ struct _HTTP_BOOT_PRIVATE_DATA { CHAR8 *FilePathUri; VOID *FilePathUriParser; =20 + // + // URI string for the endpoint host if BootFileUri contains a proxy + // server in the path + // + CHAR8 *EndPointUri; + // // Cached HTTP data // diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDxe= /HttpBootImpl.c index b4c61925b9..6fafd800bd 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c @@ -116,8 +116,14 @@ HttpBootStart ( UINTN Index; EFI_STATUS Status; CHAR8 *Uri; + CHAR8 *EndPointUri; + CHAR8 *BootFilePath; + UINTN FilePathUriLen; + UINTN EndPointUriLen; =20 - Uri =3D NULL; + Uri =3D NULL; + EndPointUri =3D NULL; + BootFilePath =3D NULL; =20 if ((Private =3D=3D NULL) || (FilePath =3D=3D NULL)) { return EFI_INVALID_PARAMETER; @@ -127,7 +133,7 @@ HttpBootStart ( // Check the URI in the input FilePath, in order to see whether it is // required to boot from a new specified boot file. // - Status =3D HttpBootParseFilePath (FilePath, &Uri); + Status =3D HttpBootParseFilePath (FilePath, &Uri, &EndPointUri); if (EFI_ERROR (Status)) { return EFI_INVALID_PARAMETER; } @@ -154,6 +160,10 @@ HttpBootStart ( FreePool (Uri); } =20 + if (EndPointUri !=3D NULL) { + FreePool (EndPointUri); + } + return Status; } } else { @@ -164,6 +174,10 @@ HttpBootStart ( FreePool (Uri); } =20 + if (EndPointUri !=3D NULL) { + FreePool (EndPointUri); + } + return EFI_ALREADY_STARTED; } } @@ -180,13 +194,63 @@ HttpBootStart ( FreePool (Uri); } =20 + if (EndPointUri !=3D NULL) { + FreePool (EndPointUri); + } + return EFI_UNSUPPORTED; } =20 // // Record the specified URI and prepare the URI parser if needed. // - Private->FilePathUri =3D Uri; + Private->EndPointUri =3D EndPointUri; + if (Private->EndPointUri !=3D NULL) { + // + // When a Proxy Server URI is included in the device path, the file pa= th + // is a part of the EndPoint URI. + // Move the file path from EndPointUri to FilePathUri + // + Status =3D HttpParseUrl ( + Private->EndPointUri, + (UINT32)AsciiStrLen (Private->EndPointUri), + FALSE, + &Private->FilePathUriParser + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status =3D HttpUrlGetPath ( + Private->EndPointUri, + Private->FilePathUriParser, + &BootFilePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Remove the file path from EndPointUri + // + EndPointUriLen =3D AsciiStrLen (EndPointUri) - AsciiStrLen (Boot= FilePath) + 1; + Private->EndPointUri =3D AllocateZeroPool (EndPointUriLen); + AsciiSPrint (Private->EndPointUri, EndPointUriLen, "%a", EndPointUri); + + // + // Add the file path to FilePathUri + // + FilePathUriLen =3D AsciiStrLen (Uri) + AsciiStrLen (BootFilePath= ) + 1; + Private->FilePathUri =3D AllocateZeroPool (FilePathUriLen); + AsciiSPrint (Private->FilePathUri, FilePathUriLen, "%a%a", Uri, BootFi= lePath); + + FreePool (BootFilePath); + FreePool (Private->FilePathUriParser); + FreePool (EndPointUri); + } else { + Private->FilePathUri =3D Uri; + } + if (Private->FilePathUri !=3D NULL) { Status =3D HttpParseUrl ( Private->FilePathUri, @@ -274,6 +338,136 @@ HttpBootDhcp ( return Status; } =20 +/** + Issue calls to HttpBootGetBootFile() based on current Boot File State + + @param[in] Private The pointer to the driver's private = data. + @param[in, out] BufferSize On input the size of Buffer in bytes= . On output with a return + code of EFI_SUCCESS, the amount of d= ata transferred to + Buffer. On output with a return code= of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retri= eve the requested file. + @param[in] Buffer The memory buffer to transfer the fi= le to. If Buffer is NULL, + then the size of the requested file = is returned in + BufferSize. + @param[out] ImageType The image type of the downloaded fil= e. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_INVALID_PARAMETER BufferSize is NULL or Buffer Size is no= t NULL but Buffer is NULL. + @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the= current directory entry. + BufferSize has been updated with the si= ze needed to complete + the request. + @retval EFI_ACCESS_DENIED Server authentication failed. + @retval Others Unexpected error happened. + +**/ +EFI_STATUS +HttpBootGetBootFileCaller ( + IN HTTP_BOOT_PRIVATE_DATA *Private, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL, + OUT HTTP_BOOT_IMAGE_TYPE *ImageType + ) +{ + HTTP_GET_BOOT_FILE_STATE State; + EFI_STATUS Status; + + if (Private->BootFileSize =3D=3D 0) { + if (Private->EndPointUri !=3D NULL) { + State =3D ConnectToProxy; + } else { + State =3D GetBootFileHead; + } + } else { + State =3D LoadBootFile; + } + + for ( ; ;) { + switch (State) { + case GetBootFileHead: + // + // Try to use HTTP HEAD method. + // + Status =3D HttpBootGetBootFile ( + Private, + TRUE, + &Private->BootFileSize, + NULL, + &Private->ImageType + ); + if ((EFI_ERROR (Status)) && (Status !=3D EFI_BUFFER_TOO_SMALL)) { + if ((Private->AuthData !=3D NULL) && (Status =3D=3D EFI_ACCESS_D= ENIED)) { + // + // Try to use HTTP HEAD method again since the Authentication = information is provided. + // + State =3D GetBootFileHead; + } else { + State =3D GetBootFileGet; + } + } else { + State =3D LoadBootFile; + } + + break; + + case GetBootFileGet: + // + // Failed to get file size by HEAD method, may be trunked encoding= , try HTTP GET method. + // + ASSERT (Private->BootFileSize =3D=3D 0); + Status =3D HttpBootGetBootFile ( + Private, + FALSE, + &Private->BootFileSize, + NULL, + &Private->ImageType + ); + if (EFI_ERROR (Status) && (Status !=3D EFI_BUFFER_TOO_SMALL)) { + State =3D GetBootFileError; + } else { + State =3D LoadBootFile; + } + + break; + + case ConnectToProxy: + Status =3D HttpBootConnectProxy (Private); + if (Status =3D=3D EFI_SUCCESS) { + State =3D GetBootFileHead; + } else { + State =3D GetBootFileError; + } + + break; + + case LoadBootFile: + if (*BufferSize < Private->BootFileSize) { + *BufferSize =3D Private->BootFileSize; + *ImageType =3D Private->ImageType; + Status =3D EFI_BUFFER_TOO_SMALL; + return Status; + } + + // + // Load the boot file into Buffer + // + Status =3D HttpBootGetBootFile ( + Private, + FALSE, + BufferSize, + Buffer, + ImageType + ); + return Status; + + case GetBootFileError: + default: + AsciiPrint ("\n Error: Could not retrieve NBP file size from HTTP= server.\n"); + return Status; + } + } +} + /** Attempt to download the boot file through HTTP message exchange. =20 @@ -345,68 +539,10 @@ HttpBootLoadFile ( } } =20 - if (Private->BootFileSize =3D=3D 0) { - // - // Discover the information about the bootfile if we haven't. - // - - // - // Try to use HTTP HEAD method. - // - Status =3D HttpBootGetBootFile ( - Private, - TRUE, - &Private->BootFileSize, - NULL, - &Private->ImageType - ); - if ((Private->AuthData !=3D NULL) && (Status =3D=3D EFI_ACCESS_DENIED)= ) { - // - // Try to use HTTP HEAD method again since the Authentication inform= ation is provided. - // - Status =3D HttpBootGetBootFile ( - Private, - TRUE, - &Private->BootFileSize, - NULL, - &Private->ImageType - ); - } else if ((EFI_ERROR (Status)) && (Status !=3D EFI_BUFFER_TOO_SMALL))= { - // - // Failed to get file size by HEAD method, may be trunked encoding, = try HTTP GET method. - // - ASSERT (Private->BootFileSize =3D=3D 0); - Status =3D HttpBootGetBootFile ( - Private, - FALSE, - &Private->BootFileSize, - NULL, - &Private->ImageType - ); - if (EFI_ERROR (Status) && (Status !=3D EFI_BUFFER_TOO_SMALL)) { - AsciiPrint ("\n Error: Could not retrieve NBP file size from HTTP= server.\n"); - goto ON_EXIT; - } - } - } - - if (*BufferSize < Private->BootFileSize) { - *BufferSize =3D Private->BootFileSize; - *ImageType =3D Private->ImageType; - Status =3D EFI_BUFFER_TOO_SMALL; - goto ON_EXIT; - } - // - // Load the boot file into Buffer + // Load the Boot File // - Status =3D HttpBootGetBootFile ( - Private, - FALSE, - BufferSize, - Buffer, - ImageType - ); + Status =3D HttpBootGetBootFileCaller (Private, BufferSize, Buffer, Image= Type); =20 ON_EXIT: HttpBootUninstallCallback (Private); diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.h b/NetworkPkg/HttpBootDxe= /HttpBootImpl.h index 55adc9cb50..e4ffc3ed48 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.h +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.h @@ -11,6 +11,14 @@ SPDX-License-Identifier: BSD-2-Clause-Patent =20 #define HTTP_BOOT_CHECK_MEDIA_WAITING_TIME EFI_TIMER_PERIOD_SECONDS(20) =20 +typedef enum { + GetBootFileHead, + GetBootFileGet, + ConnectToProxy, + LoadBootFile, + GetBootFileError +} HTTP_GET_BOOT_FILE_STATE; + /** Attempt to complete a DHCPv4 D.O.R.A or DHCPv6 S.R.A.A sequence to retri= eve the boot resource information. =20 diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.c b/NetworkPkg/HttpBoot= Dxe/HttpBootSupport.c index 236ef25931..c857488036 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.c +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.c @@ -558,6 +558,7 @@ HttpBootCheckUriScheme ( =20 @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 de= vice path. + @param[out] EndPointUriAddress The URI address string for the endpoint = host if UriAddress contains the address of a proxy server =20 @retval EFI_SUCCESS The URI string is returned. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @@ -566,19 +567,24 @@ HttpBootCheckUriScheme ( EFI_STATUS HttpBootParseFilePath ( IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT CHAR8 **UriAddress + OUT CHAR8 **UriAddress, + OUT CHAR8 **EndPointUriAddress ) { EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; URI_DEVICE_PATH *UriDevicePath; CHAR8 *Uri; + CHAR8 *TempUri; UINTN UriStrLength; =20 if (FilePath =3D=3D NULL) { return EFI_INVALID_PARAMETER; } =20 - *UriAddress =3D NULL; + Uri =3D NULL; + *UriAddress =3D NULL; + *EndPointUriAddress =3D NULL; + TempUri =3D NULL; =20 // // Extract the URI address from the FilePath @@ -601,6 +607,15 @@ HttpBootParseFilePath ( break; } =20 + if (Uri !=3D NULL) { + // + // Device Path with Proxy Server will be described as + // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv4(...)[/Dns(...)]= /Uri(ProxyServer)/Uri(EndPointServer/FilePath) + // ....../Mac(...)[/Vlan(...)][/Wi-Fi(...)]/IPv6(...)[/Dns(...)]= /Uri(ProxyServer)/Uri(EndPointServer/FilePath) + // + TempUri =3D Uri; + } + Uri =3D AllocatePool (UriStrLength + 1); if (Uri =3D=3D NULL) { return EFI_OUT_OF_RESOURCES; @@ -615,6 +630,11 @@ HttpBootParseFilePath ( TempDevicePath =3D NextDevicePathNode (TempDevicePath); } =20 + if (TempUri !=3D NULL) { + *UriAddress =3D TempUri; + *EndPointUriAddress =3D Uri; + } + return EFI_SUCCESS; } =20 diff --git a/NetworkPkg/HttpBootDxe/HttpBootSupport.h b/NetworkPkg/HttpBoot= Dxe/HttpBootSupport.h index 3698e55936..6228f37e36 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootSupport.h +++ b/NetworkPkg/HttpBootDxe/HttpBootSupport.h @@ -138,8 +138,9 @@ HttpBootCheckUriScheme ( =20 Caller need to free the buffer in the UriAddress pointer. =20 - @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 de= vice path. + @param[in] FilePath Pointer to the device path which contain= s a URI device path node. + @param[out] UriAddress The URI address string extract from the = device path. + @param[out] EndPointUriAddress The URI address string for the endpoint = host if UriAddress contains the address of a proxy server =20 @retval EFI_SUCCESS The URI string is returned. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @@ -148,7 +149,8 @@ HttpBootCheckUriScheme ( EFI_STATUS HttpBootParseFilePath ( IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT CHAR8 **UriAddress + OUT CHAR8 **UriAddress, + OUT CHAR8 **EndPointUriAddress ); =20 /** diff --git a/NetworkPkg/HttpDxe/HttpDriver.h b/NetworkPkg/HttpDxe/HttpDrive= r.h index 01a6bb7f4b..e0917f431e 100644 --- a/NetworkPkg/HttpDxe/HttpDriver.h +++ b/NetworkPkg/HttpDxe/HttpDriver.h @@ -26,6 +26,7 @@ #include #include #include +#include =20 // // UEFI Driver Model Protocols @@ -64,6 +65,7 @@ // Driver Version // #define HTTP_DRIVER_VERSION 0xa +#define URI_STR_MAX_SIZE 255 =20 // // Protocol instances diff --git a/NetworkPkg/HttpDxe/HttpDxe.inf b/NetworkPkg/HttpDxe/HttpDxe.inf index c9502d0bb6..30b7de1951 100644 --- a/NetworkPkg/HttpDxe/HttpDxe.inf +++ b/NetworkPkg/HttpDxe/HttpDxe.inf @@ -47,6 +47,7 @@ NetLib HttpLib DpcLib + PrintLib =20 [Protocols] gEfiHttpServiceBindingProtocolGuid ## BY_START diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c index 7c5c925cf7..24ce87fd7d 100644 --- a/NetworkPkg/HttpDxe/HttpImpl.c +++ b/NetworkPkg/HttpDxe/HttpImpl.c @@ -233,35 +233,45 @@ EfiHttpRequest ( EFI_HTTP_MESSAGE *HttpMsg; EFI_HTTP_REQUEST_DATA *Request; VOID *UrlParser; + VOID *EndPointUrlParser; EFI_STATUS Status; CHAR8 *HostName; + CHAR8 *EndPointHostName; UINTN HostNameSize; UINT16 RemotePort; + UINT16 EndPointRemotePort; HTTP_PROTOCOL *HttpInstance; BOOLEAN Configure; BOOLEAN ReConfigure; BOOLEAN TlsConfigure; CHAR8 *RequestMsg; CHAR8 *Url; + CHAR8 *EndPointUrl; UINTN UrlLen; CHAR16 *HostNameStr; HTTP_TOKEN_WRAP *Wrap; CHAR8 *FileUrl; UINTN RequestMsgSize; EFI_HANDLE ImageHandle; + CHAR8 *EndPointUrlMsg; =20 // // Initializations // - Url =3D NULL; - UrlParser =3D NULL; - RemotePort =3D 0; - HostName =3D NULL; - RequestMsg =3D NULL; - HostNameStr =3D NULL; - Wrap =3D NULL; - FileUrl =3D NULL; - TlsConfigure =3D FALSE; + Url =3D NULL; + UrlParser =3D NULL; + EndPointUrlParser =3D NULL; + RemotePort =3D 0; + EndPointRemotePort =3D 0; + HostName =3D NULL; + EndPointHostName =3D NULL; + RequestMsg =3D NULL; + HostNameStr =3D NULL; + Wrap =3D NULL; + FileUrl =3D NULL; + TlsConfigure =3D FALSE; + EndPointUrl =3D NULL; + EndPointUrlMsg =3D NULL; =20 if ((This =3D=3D NULL) || (Token =3D=3D NULL)) { return EFI_INVALID_PARAMETER; @@ -275,16 +285,20 @@ EfiHttpRequest ( Request =3D HttpMsg->Data.Request; =20 // - // Only support GET, HEAD, DELETE, PATCH, PUT and POST method in current= implementation. + // Only support GET, HEAD, DELETE, PATCH, PUT, CONNECT and POST method i= n current implementation. // if ((Request !=3D NULL) && (Request->Method !=3D HttpMethodGet) && (Request->Method !=3D HttpMethodHead) && (Request->Method !=3D HttpM= ethodDelete) && (Request->Method !=3D HttpMethodPut) && (Request->Method !=3D HttpMe= thodPost) && - (Request->Method !=3D HttpMethodPatch)) + (Request->Method !=3D HttpMethodPatch) && (Request->Method !=3D Http= MethodConnect)) { return EFI_UNSUPPORTED; } =20 + if ((Request->Method =3D=3D HttpMethodConnect) && (Request->EndPointUrl = =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + HttpInstance =3D HTTP_INSTANCE_FROM_PROTOCOL (This); =20 // @@ -353,11 +367,25 @@ EfiHttpRequest ( =20 UnicodeStrToAsciiStrS (Request->Url, Url, UrlLen); =20 + if (Request->EndPointUrl !=3D NULL) { + UrlLen =3D StrLen (Request->EndPointUrl) + 1; + EndPointUrl =3D AllocateZeroPool (UrlLen); + if (EndPointUrl =3D=3D NULL) { + goto Error1; + } + + UnicodeStrToAsciiStrS (Request->EndPointUrl, EndPointUrl, UrlLen); + } + // // From the information in Url, the HTTP instance will // be able to determine whether to use http or https. // - HttpInstance->UseHttps =3D IsHttpsUrl (Url); + if (HttpInstance->ProxyConnected) { + HttpInstance->UseHttps =3D IsHttpsUrl (EndPointUrl); + } else { + HttpInstance->UseHttps =3D IsHttpsUrl (Url); + } =20 // // HTTP is disabled, return directly if the URI is not HTTPS. @@ -444,9 +472,10 @@ EfiHttpRequest ( if ((HttpInstance->ConnectionClose =3D=3D FALSE) && (HttpInstance->RemotePort =3D=3D RemotePort) && (AsciiStrCmp (HttpInstance->RemoteHost, HostName) =3D=3D 0) && - (!HttpInstance->UseHttps || (HttpInstance->UseHttps && - !TlsConfigure && - (HttpInstance->TlsSessionState =3D= =3D EfiTlsSessionDataTransferring)))) + (!HttpInstance->UseHttps || + HttpInstance->ProxyConnected || (HttpInstance->UseHttps && + !TlsConfigure && + (HttpInstance->TlsSessionState= =3D=3D EfiTlsSessionDataTransferring)))) { // // Host Name and port number of the request URL are the same with = previous call to Request(). @@ -599,7 +628,7 @@ EfiHttpRequest ( goto Error2; } =20 - if (!Configure && !ReConfigure && !TlsConfigure) { + if ((!Configure && !ReConfigure) && ((HttpInstance->ProxyConnected && Tl= sConfigure) || (!TlsConfigure))) { // // For the new HTTP token, create TX TCP token events. // @@ -632,7 +661,48 @@ EfiHttpRequest ( } } =20 - Status =3D HttpGenRequestMessage (HttpMsg, FileUrl, &RequestMsg, &Reques= tMsgSize); + if (HttpInstance->Method =3D=3D HttpMethodConnect) { + Status =3D HttpParseUrl (EndPointUrl, (UINT32)AsciiStrLen (EndPointUrl= ), FALSE, &EndPointUrlParser); + if (EFI_ERROR (Status)) { + goto Error3; + } + + Status =3D HttpUrlGetHostName ( + EndPointUrl, + EndPointUrlParser, + &EndPointHostName + ); + if (EFI_ERROR (Status)) { + goto Error3; + } + + Status =3D HttpUrlGetPort (EndPointUrl, EndPointUrlParser, &EndPointRe= motePort); + if (EFI_ERROR (Status)) { + if (IsHttpsUrl (EndPointUrl)) { + EndPointRemotePort =3D HTTPS_DEFAULT_PORT; + } else { + EndPointRemotePort =3D HTTP_DEFAULT_PORT; + } + } + + EndPointUrlMsg =3D AllocateZeroPool (URI_STR_MAX_SIZE); + if (EndPointUrlMsg =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto Error3; + } + + AsciiSPrint ( + EndPointUrlMsg, + URI_STR_MAX_SIZE, + "%a:%d", + EndPointHostName, + EndPointRemotePort + ); + + Status =3D HttpGenRequestMessage (HttpMsg, EndPointUrlMsg, &RequestMsg= , &RequestMsgSize); + } else { + Status =3D HttpGenRequestMessage (HttpMsg, FileUrl, &RequestMsg, &Requ= estMsgSize); + } =20 if (EFI_ERROR (Status) || (NULL =3D=3D RequestMsg)) { goto Error3; @@ -668,6 +738,23 @@ EfiHttpRequest ( =20 DispatchDpc (); =20 + if (HttpInstance->Method =3D=3D HttpMethodConnect) { + HttpInstance->ProxyConnected =3D TRUE; + HttpInstance->EndPointRemoteHost =3D EndPointHostName; + + if (EndPointUrlParser !=3D NULL) { + HttpUrlFreeParser (EndPointUrlParser); + } + } + + if (EndPointUrlMsg !=3D NULL) { + FreePool (EndPointUrlMsg); + } + + if (EndPointUrl !=3D NULL) { + FreePool (EndPointUrl); + } + if (HostName !=3D NULL) { FreePool (HostName); } @@ -698,6 +785,20 @@ Error3: TlsCloseTxRxEvent (HttpInstance); } =20 + if (HttpInstance->Method =3D=3D HttpMethodConnect) { + if (EndPointHostName !=3D NULL) { + FreePool (EndPointHostName); + } + + if (EndPointUrlParser !=3D NULL) { + HttpUrlFreeParser (EndPointUrlParser); + } + } + + if (EndPointUrlMsg !=3D NULL) { + FreePool (EndPointUrlMsg); + } + Error2: HttpCloseConnection (HttpInstance); =20 @@ -725,6 +826,10 @@ Error1: HttpUrlFreeParser (UrlParser); } =20 + if (EndPointUrl !=3D NULL) { + FreePool (EndPointUrl); + } + return Status; } =20 diff --git a/NetworkPkg/HttpDxe/HttpProto.c b/NetworkPkg/HttpDxe/HttpProto.c index 33ae622c3f..b87fbeeb54 100644 --- a/NetworkPkg/HttpDxe/HttpProto.c +++ b/NetworkPkg/HttpDxe/HttpProto.c @@ -849,6 +849,11 @@ HttpCleanProtocol ( HttpInstance->Url =3D NULL; } =20 + if (HttpInstance->EndPointRemoteHost !=3D NULL) { + FreePool (HttpInstance->EndPointRemoteHost); + HttpInstance->EndPointRemoteHost =3D NULL; + } + NetMapClean (&HttpInstance->TxTokens); NetMapClean (&HttpInstance->RxTokens); =20 @@ -1206,6 +1211,7 @@ HttpConfigureTcp6 ( connect one TLS session if required. =20 @param[in] HttpInstance The HTTP instance private data. + @param[in] TlsConfigure The Flag indicates whether it's the new T= ls session. =20 @retval EFI_SUCCESS The TCP connection is established. @retval EFI_NOT_READY TCP4 protocol child is not created or con= figured. @@ -1214,7 +1220,8 @@ HttpConfigureTcp6 ( **/ EFI_STATUS HttpConnectTcp4 ( - IN HTTP_PROTOCOL *HttpInstance + IN HTTP_PROTOCOL *HttpInstance, + IN BOOLEAN TlsConfigure ) { EFI_STATUS Status; @@ -1237,16 +1244,18 @@ HttpConnectTcp4 ( return Status; } =20 - if (Tcp4State =3D=3D Tcp4StateEstablished) { + if ((Tcp4State =3D=3D Tcp4StateEstablished) && (!HttpInstance->ProxyConn= ected || !TlsConfigure)) { return EFI_SUCCESS; } else if (Tcp4State > Tcp4StateEstablished ) { HttpCloseConnection (HttpInstance); } =20 - Status =3D HttpCreateConnection (HttpInstance); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Tcp4 Connection fail - %x\n", Status)); - return Status; + if (!HttpInstance->ProxyConnected) { + Status =3D HttpCreateConnection (HttpInstance); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Tcp4 Connection fail - %x\n", Status)); + return Status; + } } =20 // @@ -1298,6 +1307,7 @@ HttpConnectTcp4 ( connect one TLS session if required. =20 @param[in] HttpInstance The HTTP instance private data. + @param[in] TlsConfigure The Flag indicates whether it's the new T= ls session. =20 @retval EFI_SUCCESS The TCP connection is established. @retval EFI_NOT_READY TCP6 protocol child is not created or con= figured. @@ -1306,7 +1316,8 @@ HttpConnectTcp4 ( **/ EFI_STATUS HttpConnectTcp6 ( - IN HTTP_PROTOCOL *HttpInstance + IN HTTP_PROTOCOL *HttpInstance, + IN BOOLEAN TlsConfigure ) { EFI_STATUS Status; @@ -1330,16 +1341,18 @@ HttpConnectTcp6 ( return Status; } =20 - if (Tcp6State =3D=3D Tcp6StateEstablished) { + if ((Tcp6State =3D=3D Tcp6StateEstablished) && (!HttpInstance->ProxyConn= ected || !TlsConfigure)) { return EFI_SUCCESS; } else if (Tcp6State > Tcp6StateEstablished ) { HttpCloseConnection (HttpInstance); } =20 - Status =3D HttpCreateConnection (HttpInstance); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Tcp6 Connection fail - %x\n", Status)); - return Status; + if (!HttpInstance->ProxyConnected) { + Status =3D HttpCreateConnection (HttpInstance); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Tcp6 Connection fail - %x\n", Status)); + return Status; + } } =20 // @@ -1434,7 +1447,7 @@ HttpInitSession ( // // Connect TCP. // - Status =3D HttpConnectTcp4 (HttpInstance); + Status =3D HttpConnectTcp4 (HttpInstance, TlsConfigure); if (EFI_ERROR (Status)) { return Status; } @@ -1452,7 +1465,7 @@ HttpInitSession ( // // Connect TCP. // - Status =3D HttpConnectTcp6 (HttpInstance); + Status =3D HttpConnectTcp6 (HttpInstance, TlsConfigure); if (EFI_ERROR (Status)) { return Status; } diff --git a/NetworkPkg/HttpDxe/HttpProto.h b/NetworkPkg/HttpDxe/HttpProto.h index 620eb39158..2e8d516359 100644 --- a/NetworkPkg/HttpDxe/HttpProto.h +++ b/NetworkPkg/HttpDxe/HttpProto.h @@ -165,6 +165,12 @@ typedef struct _HTTP_PROTOCOL { =20 CHAR8 *Url; =20 + // + // Proxy Server Support + // + CHAR8 *EndPointRemoteHost; + BOOLEAN ProxyConnected; + // // Https Support // @@ -398,6 +404,7 @@ HttpConfigureTcp6 ( connect one TLS session if required. =20 @param[in] HttpInstance The HTTP instance private data. + @param[in] TlsConfigure The Flag indicates whether it's the new T= ls session. =20 @retval EFI_SUCCESS The TCP connection is established. @retval EFI_NOT_READY TCP4 protocol child is not created or con= figured. @@ -406,7 +413,8 @@ HttpConfigureTcp6 ( **/ EFI_STATUS HttpConnectTcp4 ( - IN HTTP_PROTOCOL *HttpInstance + IN HTTP_PROTOCOL *HttpInstance, + IN BOOLEAN TlsConfigure ); =20 /** @@ -414,6 +422,7 @@ HttpConnectTcp4 ( connect one TLS session if required. =20 @param[in] HttpInstance The HTTP instance private data. + @param[in] TlsConfigure The Flag indicates whether it's the new T= ls session. =20 @retval EFI_SUCCESS The TCP connection is established. @retval EFI_NOT_READY TCP6 protocol child is not created or con= figured. @@ -422,7 +431,8 @@ HttpConnectTcp4 ( **/ EFI_STATUS HttpConnectTcp6 ( - IN HTTP_PROTOCOL *HttpInstance + IN HTTP_PROTOCOL *HttpInstance, + IN BOOLEAN TlsConfigure ); =20 /** diff --git a/NetworkPkg/HttpDxe/HttpsSupport.c b/NetworkPkg/HttpDxe/HttpsSu= pport.c index ad611e7c38..7dc2b752ec 100644 --- a/NetworkPkg/HttpDxe/HttpsSupport.c +++ b/NetworkPkg/HttpDxe/HttpsSupport.c @@ -644,11 +644,15 @@ TlsConfigureSession ( // // TlsConfigData initialization // - HttpInstance->TlsConfigData.ConnectionEnd =3D EfiTlsClient; - HttpInstance->TlsConfigData.VerifyMethod =3D EFI_TLS_VERIFY_PEER; - HttpInstance->TlsConfigData.VerifyHost.Flags =3D EFI_TLS_VERIFY_FLAG_= NONE; - HttpInstance->TlsConfigData.VerifyHost.HostName =3D HttpInstance->Remote= Host; - HttpInstance->TlsConfigData.SessionState =3D EfiTlsSessionNotStar= ted; + HttpInstance->TlsConfigData.ConnectionEnd =3D EfiTlsClient; + HttpInstance->TlsConfigData.SessionState =3D EfiTlsSessionNotStarted; + HttpInstance->TlsConfigData.VerifyMethod =3D EFI_TLS_VERIFY_PEER; + HttpInstance->TlsConfigData.VerifyHost.Flags =3D EFI_TLS_VERIFY_FLAG_NON= E; + if (HttpInstance->ProxyConnected) { + HttpInstance->TlsConfigData.VerifyHost.HostName =3D HttpInstance->EndP= ointRemoteHost; + } else { + HttpInstance->TlsConfigData.VerifyHost.HostName =3D HttpInstance->Remo= teHost; + } =20 // // EfiTlsConnectionEnd, diff --git a/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c b/NetworkPkg/Librar= y/DxeHttpLib/DxeHttpLib.c index 6a5d78629b..45087a1935 100644 --- a/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c +++ b/NetworkPkg/Library/DxeHttpLib/DxeHttpLib.c @@ -1927,6 +1927,11 @@ HttpGenRequestMessage ( CopyMem (RequestPtr, HTTP_METHOD_DELETE, StrLength); RequestPtr +=3D StrLength; break; + case HttpMethodConnect: + StrLength =3D sizeof (HTTP_METHOD_CONNECT) - 1; + CopyMem (RequestPtr, HTTP_METHOD_CONNECT, StrLength); + RequestPtr +=3D StrLength; + break; default: ASSERT (FALSE); Status =3D EFI_INVALID_PARAMETER; --=20 2.36.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#94092): https://edk2.groups.io/g/devel/message/94092 Mute This Topic: https://groups.io/mt/93837213/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-