From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from NAM10-MW2-obe.outbound.protection.outlook.com (NAM10-MW2-obe.outbound.protection.outlook.com [40.107.94.54]) by mx.groups.io with SMTP id smtpd.web10.45934.1590473642657334148 for ; Mon, 25 May 2020 23:14:02 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@vmware.com header.s=selector2 header.b=iC93Vxz4; spf=pass (domain: vmware.com, ip: 40.107.94.54, mailfrom: awarkentin@vmware.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=d/LhStexB+mpygVal34mvpqkdd7DeM8U8SCD/R2DkWoXn09mKPYQS/RHJhqdxzGT1pRvlTHIkpVXwH4VimNN+JbHaUQROytoCi7U215DYmOXZTMuS0J78d9oV/VP/UvUWDYGXB3kacjTTL6TRnFTcjPL7oL3gjj1t8o6ZPv2ap7P2TgNZu16qa7xuu5Q4X9aHAm4zoOSMwU3PBIqFwNyocHEK0wrKUEKebmgj5+9uXv+pVNATCstIoR8o6tTDlnKXOBzMf416qnRKUbhoNBtagPaUXrmZwmVeJQ17E9XRE9UGEDAS8vogC3MAmhRDfQj5tt08KjO4NGn8bdUaJNXUg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kpacYOvn9FFR7Nhqc2m3jzevQ+OOctceSFogSDj7XQo=; b=bo553p9Irn+EzmSLMS/hSxtTh+6QtBw2vNTC9tvR1oIVrZRrWTA0Wda1V8IdBzd0H0fzxgj8d1FSSN0z7o9stoi+1uOfpzoHddjx1EWLq8+Fg2QHYpmPzHP+hKD7s7+40MOTXMZ42l2MaooRNzlI+Di7GXGzAmA2GXPprlGkrD4k8Svfh4w58wGXzAXI6Pjama3h0qmTPBsSiEUnChm+jWbTicbAqTMh/zZeO7hde+AfK/b4qLQoitnU9DU8exI8gpPp/TZ9Ll5cHgfQiVHxC6/y+0fSpaEojx03VrYSVWlvCfPabyu1ytfiiLzdLANyfUoiQPRPv0kwiMA1TtoIdA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=vmware.com; dmarc=pass action=none header.from=vmware.com; dkim=pass header.d=vmware.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vmware.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=kpacYOvn9FFR7Nhqc2m3jzevQ+OOctceSFogSDj7XQo=; b=iC93Vxz45foIWA/DF8CfZvtEgJkbLjDyg8EgRenKZ+pXA5E0RhW3kMzhXc1yflw5b8L16I/h4+9yYJw0B+LkOqjvgbnbXywiQZvKBv+ExLFXEf2mZveu5b7QEKfCHzMmdzJ29xP4hUKbI77a2kJ3E6fInu8B2zQs6aMdmPKqnkA= Received: from BN6PR05MB3411.namprd05.prod.outlook.com (2603:10b6:405:43::23) by BN6PR05MB3138.namprd05.prod.outlook.com (2603:10b6:404:bb::16) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3045.8; Tue, 26 May 2020 06:13:58 +0000 Received: from BN6PR05MB3411.namprd05.prod.outlook.com ([fe80::e1ef:31eb:c802:aef0]) by BN6PR05MB3411.namprd05.prod.outlook.com ([fe80::e1ef:31eb:c802:aef0%3]) with mapi id 15.20.3045.014; Tue, 26 May 2020 06:13:58 +0000 From: "Andrei Warkentin" To: "devel@edk2.groups.io" , "andrey.warkentin@gmail.com" , "maciej.rabeda@linux.intel.com" CC: "jiaxin.wu@intel.com" , "siyuan.fu@intel.com" Subject: Re: [edk2-devel] [edk2][PATCH 1/1] NetworkPkg/HttpBootDxe: handle servers which may FIN after file sizing in HttpBootLoadFile Thread-Topic: [edk2-devel] [edk2][PATCH 1/1] NetworkPkg/HttpBootDxe: handle servers which may FIN after file sizing in HttpBootLoadFile Thread-Index: AQHWMHHPmsuSbIlXpUud3kosrPxKSai4xNUAgAEh00M= Date: Tue, 26 May 2020 06:13:58 +0000 Message-ID: References: <20200522194659.54423-1-andrey.warkentin@gmail.com>,<3ae431b3-e588-d39d-5f73-c5cc20c712d0@linux.intel.com> In-Reply-To: <3ae431b3-e588-d39d-5f73-c5cc20c712d0@linux.intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: edk2.groups.io; dkim=none (message not signed) header.d=none;edk2.groups.io; dmarc=none action=none header.from=vmware.com; x-originating-ip: [98.214.99.181] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 1588d7c4-b5f1-467f-c546-08d8013bfa5c x-ms-traffictypediagnostic: BN6PR05MB3138: x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:1923; x-forefront-prvs: 041517DFAB x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: 4Ch4FwJhrtr6OWU74DoOkCpdDyj78AL/OINy1d7bePWr9jGvYkuPpsRFrUlAHgizzhVJA+bMWK9F6rSZozYvAseKstgI065xeWJnZODhLiD/tqdkSBJhEnwcQbahL93vSEg0FHHxqGcX1jj7wgRIdjcZ4mnEPB9JjL6kMAunpw6QtOX+O23PeEJaXeyqxUIgrHJ+Gplotb/EclY7fzVOdGRbq4z47xbC1qxR32c8Cf4bYt2gNwL58iAKD5OC87ZRQlK8RX1YvUADuJpqeke3n6XhZfu0l45nS712v5sV5g5/BVVAvld7rQxdQWxz2BpVMfdUtsRFO/MkISnuxJ+/4xqsOC4L/mqj9Ajiebu2/khJHOCz+hlDSLckVukv14Gk54suKsUdz/W14kqo6Apr1Q== x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BN6PR05MB3411.namprd05.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(6019001)(4636009)(39860400002)(366004)(396003)(376002)(136003)(346002)(269900001)(166002)(55016002)(19627405001)(2906002)(83080400001)(316002)(4326008)(9686003)(76236002)(76116006)(186003)(52536014)(64756008)(26005)(71200400001)(5660300002)(33656002)(966005)(86362001)(110136005)(54906003)(478600001)(7696005)(53546011)(6506007)(8676002)(8936002)(66556008)(66946007)(66476007)(66446008);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata: bHABnf0UQQ3GLyojZRGLyWUF5CzeMLbplPLxf2RkpRu8/9EKieMDk9pXxPirf/zFNGcRh2diW0dlYfbrHdl7+nbXs1QACpdegtpCqLPmw0Xrh/csYADl/nxu+8UqkzvFJCRRYb4o2cg+CQBqdpkboh2QZVFRewCkfojLlRVK0Q3pko7RBmqA3oIj7tv5m/aPGDneC9C0OdkdlS0TCXHIW+acNFgss/lVt7HqFHAjKk51BU+WW2wQLivLRm1uLAY9CZny9w1tt+z+jQ/az0t9Dv7wMPkOaj8SEVmeBP5JSYyCMtw+u3MC0Y9SYR5UpWaydQOMPxOIS9Q03ZX30BXFk1i8nRmvp4lEfZ9+cVsGppXQI+1Uh6bZeeSEpQby12qm3fXMjKwPg0WfrQHq30nk31XdAOlQJgJRuntocpk1AEW4AWLeugUhZHy7NfEWZYynyS/eAbXDRO9xQWW4x9WymQKRstkpcsH8H4atBL3pHGQ= x-ms-exchange-transport-forked: True MIME-Version: 1.0 X-OriginatorOrg: vmware.com X-MS-Exchange-CrossTenant-Network-Message-Id: 1588d7c4-b5f1-467f-c546-08d8013bfa5c X-MS-Exchange-CrossTenant-originalarrivaltime: 26 May 2020 06:13:58.6688 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: b39138ca-3cee-4b4a-a4d6-cd83d9dd62f0 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: R8M2OsE20sW8EYePYKmUO55pInkYR8XEQinc+VpeRHKW1qDxEYPy1i3yOggSZmAvzjFjCI2BGu9BPWVP4FNIkA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN6PR05MB3138 Content-Language: en-US Content-Type: multipart/alternative; boundary="_000_BN6PR05MB341162F51CDEB95CC1FE669BB9B00BN6PR05MB3411namp_" --_000_BN6PR05MB341162F51CDEB95CC1FE669BB9B00BN6PR05MB3411namp_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Maciej, Thanks for your analysis. The way I see it, there are many people out there expecting HttpBoot to wo= rk with the Python server - which without manual hacking is HTTP/1.0 and no= t HTTP/1.1. I think it's fine to reject 1.0 but then HttpBoot should explic= itly reject 1.0 with an appropriate message and *refuse* to boot. Today it'= s in the area where it may work and may not. 1.1 vs 1.0 aside, don't you think there should be a bit of resiliency to t= he client? As it stands right now, an arbitrary FIN between the requests g= ets the user an "unexpected network error" (or similar), with no clear indi= cation it's a server misconfiguration, a network error (which one?) or some= such. With that in mind I see the proposed fix as being a lesser evil (fri= endly to end user) than creating a pedantic HttpBoot client which will fail= because it doesn't operate in an ideal environment. What do you think? A ________________________________ From: devel@edk2.groups.io on behalf of Maciej Rabe= da via groups.io Sent: Monday, May 25, 2020 7:49 AM To: devel@edk2.groups.io ; andrey.warkentin@gmail.co= m Cc: jiaxin.wu@intel.com ; siyuan.fu@intel.com Subject: Re: [edk2-devel] [edk2][PATCH 1/1] NetworkPkg/HttpBootDxe: handle= servers which may FIN after file sizing in HttpBootLoadFile Copying my comments from Bugzilla: I have gone through the Wireshark trace that you have provided. It seems t= o be all clear now and the approach to the issue must change. HttpBootDxe supports HTTP 1.1 and assumes that the HTTP session stays pers= istent (single TCP connection for multiple requests instead of one for each= HTTP request/response pair). https://en.wikipedia.org/wiki/HTTP_persistent= _connection I am hesitant to introduce HTTP/1.0 keep-alive additions to the header. Ki= ndly request more debugging on Python server side whether to confirm that i= mplementation you are using supports HTTP/1.1. >>From what I see in here: https://github.com/python/cpython/blob/master/Lib= /http/server.py http.server has support for HTTP/1.1 and assumption on not closing the con= nection. At the time of writing this comment, it is line 311: if version_number >=3D (1, 1) and self.protocol_version >=3D "HTTP/1.1": self.close_connection =3D False Putting the patch on hold (with trend for rejecting with no support for HT= TP/1.0 keep-alive). Additional comment: https://github.com/python/cpython/blob/master/Lib/http/server.py Line 616: # The version of the HTTP protocol we support. # Set this to HTTP/1.1 to enable automatic keepalive protocol_version =3D "HTTP/1.0" Please modify it that variable to "HTTP/1.1". Your scenario should start w= orking. Please come back to me with confirmation. Thanks, Maciej On 22-May-20 21:46, Andrei Warkentin wrote: This is v2 with Maciej Rabeda's feedback. Python http.server seems to FIN after the first HEAD request to size the loaded file is completed and ACKed. What happens next is interesting. On low latency connections, the GET request to download may get sent after the server sends the FIN but before the client has a chance to process it. The net result is: - Server ignores GET - HttpBootLoadFile returns EFI_CONNECTION_FIN. Boot fails. In the other case, client handles the FIN before attempting the GET, so there's a proper three-way handshake as part of GET. The solution is to retry HttpBootLoadFile 2 times if it returns EFI_CONNECTION_FIN. This is because HttpBootLoadFile may issue up to 3 requests: HEAD/GET to get size and final GET to load. Some servers may send a FIN after each request. The first request (HEAD) is not supposed to fail this way, so only the two subsequent GET request may result in a FIN. Fixes https://bugzilla.tianocore.org/show_bug.cgi?id=3D2720 This what the boot looks like now (when using that Python server): Start HTTP Boot over IPv4.... Station IP address is 10.0.1.186 URI: http://10.0.1.57/bootaa64.efi Error: Server has terminated the connection. URI: http://10.0.1.57/bootaa64.efi File Size: 179160 Bytes Downloading...100% Cc: Maciej Rabeda Cc: Jiaxin Wu Cc: Siyuan Fu Signed-off-by: Andrei Warkentin --- NetworkPkg/HttpBootDxe/HttpBootImpl.c | 35 +++++++++++++++++++- NetworkPkg/HttpDxe/HttpImpl.c | 5 +++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDx= e/HttpBootImpl.c index 4a51f35cdd..1a251b4347 100644 --- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c +++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c @@ -288,6 +288,7 @@ HttpBootDhcp ( @retval EFI_NOT_STARTED The driver is in stopped state. @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read= the boot file. BufferSize has been updated with the size needed t= o complete the request. + @retval EFI_CONNECTION_FIN Server had closed the connection wh= ile we were waiting downloading. @retval EFI_DEVICE_ERROR An unexpected network error occurre= d. @retval Others Other errors as indicated. @@ -408,6 +409,8 @@ ON_EXIT: AsciiPrint ("\n Error: Server response timeout.\n"); } else if (Status =3D=3D EFI_ABORTED) { AsciiPrint ("\n Error: Remote boot cancelled.\n"); + } else if (Status =3D=3D EFI_CONNECTION_FIN) { + AsciiPrint ("\n Error: Server has terminated the connection.\n"); } else if (Status !=3D EFI_BUFFER_TOO_SMALL) { AsciiPrint ("\n Error: Unexpected network error.\n"); } @@ -553,6 +556,7 @@ HttpBootDxeLoadFile ( BOOLEAN UsingIpv6; EFI_STATUS Status; HTTP_BOOT_IMAGE_TYPE ImageType; + UINTN MaxTries; if (This =3D=3D NULL || BufferSize =3D=3D NULL || FilePath =3D=3D NULL)= { return EFI_INVALID_PARAMETER; @@ -598,13 +602,42 @@ HttpBootDxeLoadFile ( // Load the boot file. // ImageType =3D ImageTypeMax; - Status =3D HttpBootLoadFile (Private, BufferSize, Buffer, &ImageType); + // + // HttpBootLoadFile may issue up to 2 requests: HEAD/GET to get + // size and final GET to load. Some servers may send a FIN after + // each request. The first request (HEAD) is not supposed to + // fail this way, so only the two possible GETs need the special + // handling. + // + MaxTries =3D 2; + do { + Status =3D HttpBootLoadFile (Private, BufferSize, Buffer, &ImageType)= ; + if (Status =3D=3D EFI_CONNECTION_FIN) { + if (Private->HttpCreated) { + // + // Tear down HTTP/TCP state entirely. Http->Configure (NULL) is n= ot + // sufficient (EFI_ACCESS_DENIED from TCP stack on subsequent + // HttpBootLoadFile. + // + HttpIoDestroyIo (&Private->HttpIo); + Private->HttpCreated =3D FALSE; + } + } + } while (MaxTries-- && Status =3D=3D EFI_CONNECTION_FIN); + if (EFI_ERROR (Status)) { if (Status =3D=3D EFI_BUFFER_TOO_SMALL && (ImageType =3D=3D ImageType= VirtualCd || ImageType =3D=3D ImageTypeVirtualDisk)) { Status =3D EFI_WARN_FILE_SYSTEM; } else if (Status !=3D EFI_BUFFER_TOO_SMALL) { HttpBootStop (Private); } + if (Status =3D=3D EFI_CONNECTION_FIN) { + // + // EFI_CONNECTION_FIN is not an expected error for EFI_LOAD_FILE_PR= OTOCOL.LoadFile(), so + // map it to closest matching error. Note: already logged the error= in HttpBootLoadFile. + // + Status =3D EFI_ABORTED; + } return Status; } diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c index 5a6ecbc9d9..34a33b09f7 100644 --- a/NetworkPkg/HttpDxe/HttpImpl.c +++ b/NetworkPkg/HttpDxe/HttpImpl.c @@ -959,6 +959,8 @@ HttpBodyParserCallback ( @retval EFI_OUT_OF_RESOURCES Failed to complete the operation due to= lack of resources. @retval EFI_NOT_READY Can't find a corresponding Tx4Token/Tx6= Token or the EFI_HTTP_UTILITIES_PROTOCOL is not = available. + @retval EFI_CONNECTION_FIN Server had closed the connection while = we were waiting for + a response. **/ EFI_STATUS @@ -1528,6 +1530,9 @@ Error: @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resour= ces. @retval EFI_ACCESS_DENIED An open TCP connection is not present w= ith the host specified by response URL. + + @retval EFI_CONNECTION_FIN Server had closed the connection while = we were waiting for + a response. **/ EFI_STATUS EFIAPI --_000_BN6PR05MB341162F51CDEB95CC1FE669BB9B00BN6PR05MB3411namp_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable
Hi Maciej,

Thanks for your analysis.

The way I see it, there are many people out there expecting HttpBoot to wo= rk with the Python server - which without manual hacking is HTTP/1.0 and no= t HTTP/1.1. I think it's fine to reject 1.0 but then HttpBoot should explic= itly reject 1.0 with an appropriate message and *refuse* to boot. Today it's in the area where it may work an= d may not.

1.1 vs 1.0 aside, don't you think there should be a bit of resiliency to t= he client? As it stands right now, an arbitrary FIN  between the reque= sts gets the user an "unexpected network error" (or similar), wit= h no clear indication it's a server misconfiguration, a network error (which one?) or some such. With that in mind I see the pr= oposed fix as being a lesser evil (friendly to end user) than creating a pe= dantic HttpBoot client which will fail because it doesn't operate in an ide= al environment.

What do you think?

A

From: devel@edk2.groups.io= <devel@edk2.groups.io> on behalf of Maciej Rabeda via groups.io <= maciej.rabeda=3Dlinux.intel.com@groups.io>
Sent: Monday, May 25, 2020 7:49 AM
To: devel@edk2.groups.io <devel@edk2.groups.io>; andrey.warke= ntin@gmail.com <andrey.warkentin@gmail.com>
Cc: jiaxin.wu@intel.com <jiaxin.wu@intel.com>; siyuan.fu@inte= l.com <siyuan.fu@intel.com>
Subject: Re: [edk2-devel] [edk2][PATCH 1/1] NetworkPkg/HttpBootDxe:= handle servers which may FIN after file sizing in HttpBootLoadFile
 
Copying my comments from Bugzilla:
I have=
 gone through the Wireshark trace that you have provided. It seems to be al=
l clear now and the approach to the issue must change.

HttpBootDxe supports HTTP 1.1 and assumes that the HTTP session stays pers=
istent (single TCP connection for multiple requests instead of one for each=
 HTTP request/response pair). https://en.wikipedia.org/wiki/HTTP_persistent_connection

I am hesitant to introduce HTTP/1.0 keep-alive additions to the header. Ki=
ndly request more debugging on Python server side whether to confirm that i=
mplementation you are using supports HTTP/1.1.

>>From what I see in here: https://github.com/python/cpython/blo=
b/master/Lib/http/server.py

http.server has support for HTTP/1.1 and assumption on not closing the con=
nection. At the time of writing this comment, it is line 311:

if version_number >=3D (1, 1) and self.protocol_version >=3D "H=
TTP/1.1":
    self.close_connection =3D False

Putting the patch on hold (with trend for rejecting with no support for HT=
TP/1.0 keep-alive).

Additional comment:

https://github.com/python/cpython/blob/master/Lib/http/serve=
r.py

Line 616:

# The version of the HTTP protocol we support.
# Set this to HTTP/1.1 to enable automatic keepalive
protocol_version =3D "HTTP/1.0"

Please modify it that variable to "HTTP/1.1". Your scenario shou=
ld start working.

Please come back to me with confirmation.

Thanks,
Maciej

On 22-May-20 21:46, Andrei Warkentin wrot= e:
This is v2 with Maciej Rabeda's feedback.

Python http.server seems to FIN after the first HEAD request to size
the loaded file is completed and ACKed. What happens next is interesting.
On low latency connections, the GET request to download may get sent
after the server sends the FIN but before the client has a chance to
process it. The net result is:
- Server ignores GET
- HttpBootLoadFile returns EFI_CONNECTION_FIN. Boot fails.

In the other case, client handles the FIN before attempting the GET,
so there's a proper three-way handshake as part of GET.

The solution is to retry HttpBootLoadFile 2 times if it returns
EFI_CONNECTION_FIN. This is because HttpBootLoadFile may issue up to
3 requests: HEAD/GET to get size and final GET to load. Some servers
may send a FIN after each request. The first request (HEAD) is not
supposed to fail this way, so only the two subsequent GET request
may result in a FIN.

Fixes https://bugzill=
a.tianocore.org/show_bug.cgi?id=3D2720

This what the boot looks like now (when using that Python server):
Start HTTP Boot over IPv4....
  Station IP address is 10.0.1.186

  URI: http://10.0.1.57/bootaa64.efi

 Error: Server has terminated the connection.

  URI: http://10.0.1.57/bootaa64.efi
  File Size: 179160 Bytes
  Downloading...100%

Cc: Maciej Rabeda <maciej.rabeda@linux.intel.com>
Cc: Jiaxin Wu <jiaxin.wu@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Signed-off-by: Andrei Warkentin <andrey.warkentin@gmail.com><=
/a>
---
 NetworkPkg/HttpBootDxe/HttpBootImpl.c | 35 ++++++=
+++++++++++++-
 NetworkPkg/HttpDxe/HttpImpl.c         |  5 +++
 2 files changed, 39 insertions(+), 1 deletion(-)

diff --git a/NetworkPkg/HttpBootDxe/HttpBootImpl.c b/NetworkPkg/HttpBootDx=
e/HttpBootImpl.c
index 4a51f35cdd..1a251b4347 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootImpl.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootImpl.c
@@ -288,6 +288,7 @@ HttpBootDhcp (
   @retval EFI_NOT_STARTED             The driver is in stopped state.
   @retval EFI_BUFFER_TOO_SMALL        The BufferSize is too small to read=
 the boot file. BufferSize has
                                       been updated with the size needed t=
o complete the request.
+  @retval EFI_CONNECTION_FIN          Server had closed the connectio=
n while we were waiting downloading.
   @retval EFI_DEVICE_ERROR            An unexpected network error occurre=
d.
   @retval Others                      Other errors as indicated.
=20
@@ -408,6 +409,8 @@ ON_EXIT:
       AsciiPrint ("\n  Error: Server response timeout.\n");
     } else if (Status =3D=3D EFI_ABORTED) {
       AsciiPrint ("\n  Error: Remote boot cancelled.\n");
+    } else if (Status =3D=3D EFI_CONNECTION_FIN) {
+      AsciiPrint ("\n Error: Server has terminated the connectio=
n.\n");
     } else if (Status !=3D EFI_BUFFER_TOO_SMALL) {
       AsciiPrint ("\n  Error: Unexpected network error.\n");
     }
@@ -553,6 +556,7 @@ HttpBootDxeLoadFile (
   BOOLEAN                       UsingIpv6;
   EFI_STATUS                    Status;
   HTTP_BOOT_IMAGE_TYPE          ImageType;
+  UINTN                         MaxTries;
=20
   if (This =3D=3D NULL || BufferSize =3D=3D NULL || FilePath =3D=3D NULL)=
 {
     return EFI_INVALID_PARAMETER;
@@ -598,13 +602,42 @@ HttpBootDxeLoadFile (
   // Load the boot file.
   //
   ImageType =3D ImageTypeMax;
-  Status =3D HttpBootLoadFile (Private, BufferSize, Buffer, &ImageTyp=
e);
+  //
+  // HttpBootLoadFile may issue up to 2 requests: HEAD/GET to get
+  // size and final GET to load. Some servers may send a FIN after
+  // each request. The first request (HEAD) is not supposed to
+  // fail this way, so only the two possible GETs need the special
+  // handling.
+  //
+  MaxTries =3D 2;
+  do {
+    Status =3D HttpBootLoadFile (Private, BufferSize, Buffer, &Im=
ageType);
+    if (Status =3D=3D EFI_CONNECTION_FIN) {
+      if (Private->HttpCreated) {
+        //
+        // Tear down HTTP/TCP state entirely. Http->Configure (NUL=
L) is not
+        // sufficient (EFI_ACCESS_DENIED from TCP stack on subsequent
+        // HttpBootLoadFile.
+        //
+        HttpIoDestroyIo (&Private->HttpIo);
+        Private->HttpCreated =3D FALSE;
+      }
+    }
+  } while (MaxTries-- && Status =3D=3D EFI_CONNECTION_FIN);
+
   if (EFI_ERROR (Status)) {
     if (Status =3D=3D EFI_BUFFER_TOO_SMALL && (ImageType =3D=3D I=
mageTypeVirtualCd || ImageType =3D=3D ImageTypeVirtualDisk)) {
       Status =3D EFI_WARN_FILE_SYSTEM;
     } else if (Status !=3D EFI_BUFFER_TOO_SMALL) {
       HttpBootStop (Private);
     }
+    if (Status =3D=3D EFI_CONNECTION_FIN) {
+      //
+      // EFI_CONNECTION_FIN is not an expected error for EFI_LOAD_FIL=
E_PROTOCOL.LoadFile(), so
+      // map it to closest matching error. Note: already logged the e=
rror in HttpBootLoadFile.
+      //
+      Status =3D EFI_ABORTED;
+    }
     return Status;
   }
=20
diff --git a/NetworkPkg/HttpDxe/HttpImpl.c b/NetworkPkg/HttpDxe/HttpImpl.c
index 5a6ecbc9d9..34a33b09f7 100644
--- a/NetworkPkg/HttpDxe/HttpImpl.c
+++ b/NetworkPkg/HttpDxe/HttpImpl.c
@@ -959,6 +959,8 @@ HttpBodyParserCallback (
   @retval EFI_OUT_OF_RESOURCES    Failed to complete the operation due to=
 lack of resources.
   @retval EFI_NOT_READY           Can't find a corresponding Tx4Token/Tx6=
Token or
                                   the EFI_HTTP_UTILITIES_PROTOCOL is not =
available.
+  @retval EFI_CONNECTION_FIN      Server had closed the connection wh=
ile we were waiting for
+                                  a response.
=20
 **/
 EFI_STATUS
@@ -1528,6 +1530,9 @@ Error:
   @retval EFI_OUT_OF_RESOURCES    Could not allocate enough system resour=
ces.
   @retval EFI_ACCESS_DENIED       An open TCP connection is not present w=
ith the host
                                   specified by response URL.
+
+  @retval EFI_CONNECTION_FIN      Server had closed the connection wh=
ile we were waiting for
+                                  a response.
 **/
 EFI_STATUS
 EFIAPI

--_000_BN6PR05MB341162F51CDEB95CC1FE669BB9B00BN6PR05MB3411namp_--