]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/HttpDxe/HttpProto.c
SecurityPkg/TcgPhysicalPresenceLib: Replace the ASSERT with error code
[mirror_edk2.git] / NetworkPkg / HttpDxe / HttpProto.c
index 13d5748378e3e645101a4bd8128390e4ddf378af..bacfbc99584711c85f1a35422db1795c835c142d 100644 (file)
@@ -1,22 +1,16 @@
 /** @file\r
   Miscellaneous routines for HttpDxe driver.\r
 \r
-Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
-(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  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
+Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "HttpDriver.h"\r
 \r
 /**\r
-  The common notify function used in HTTP driver. \r
+  The common notify function used in HTTP driver.\r
 \r
   @param[in]  Event   The event signaled.\r
   @param[in]  Context The context.\r
@@ -37,7 +31,7 @@ HttpCommonNotify (
 }\r
 \r
 /**\r
-  The notify function associated with TxToken for Tcp4->Transmit().\r
+  The notify function associated with Tx4Token for Tcp4->Transmit() or Tx6Token for Tcp6->Transmit().\r
 \r
   @param[in]  Context The context.\r
 \r
@@ -49,26 +43,47 @@ HttpTcpTransmitNotifyDpc (
   )\r
 {\r
   HTTP_TOKEN_WRAP          *Wrap;\r
+  HTTP_PROTOCOL            *HttpInstance;\r
 \r
   if (Context == NULL) {\r
     return ;\r
   }\r
 \r
-  Wrap = (HTTP_TOKEN_WRAP *) Context;\r
-  Wrap->HttpToken->Status = Wrap->TcpWrap.TxToken.CompletionToken.Status;\r
-  gBS->SignalEvent (Wrap->HttpToken->Event);\r
+  Wrap         = (HTTP_TOKEN_WRAP *) Context;\r
+  HttpInstance = Wrap->HttpInstance;\r
 \r
-  //\r
-  // Free resources.\r
-  //\r
-  if (Wrap->TcpWrap.TxToken.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
-    FreePool (Wrap->TcpWrap.TxToken.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
-  }\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+      Wrap->HttpToken->Status = Wrap->TcpWrap.Tx4Token.CompletionToken.Status;\r
+      gBS->SignalEvent (Wrap->HttpToken->Event);\r
+\r
+      //\r
+      // Free resources.\r
+      //\r
+      if (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+        FreePool (Wrap->TcpWrap.Tx4Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
+      }\r
+\r
+      if (Wrap->TcpWrap.Tx4Token.CompletionToken.Event != NULL) {\r
+        gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);\r
+      }\r
+\r
+  } else {\r
+    Wrap->HttpToken->Status = Wrap->TcpWrap.Tx6Token.CompletionToken.Status;\r
+    gBS->SignalEvent (Wrap->HttpToken->Event);\r
+\r
+    //\r
+    // Free resources.\r
+    //\r
+    if (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+      FreePool (Wrap->TcpWrap.Tx6Token.Packet.TxData->FragmentTable[0].FragmentBuffer);\r
+    }\r
 \r
-  if (Wrap->TcpWrap.TxToken.CompletionToken.Event != NULL) {\r
-    gBS->CloseEvent (Wrap->TcpWrap.TxToken.CompletionToken.Event);\r
+    if (Wrap->TcpWrap.Tx6Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Tx6Token.CompletionToken.Event);\r
+    }\r
   }\r
 \r
+\r
   Wrap->TcpWrap.IsTxDone = TRUE;\r
 \r
   //\r
@@ -98,9 +113,8 @@ HttpTcpTransmitNotify (
   QueueDpc (TPL_CALLBACK, HttpTcpTransmitNotifyDpc, Context);\r
 }\r
 \r
-\r
 /**\r
-  The notify function associated with RxToken for Tcp4->Receive ().\r
+  The notify function associated with Rx4Token for Tcp4->Receive () or Rx6Token for Tcp6->Receive().\r
 \r
   @param[in]  Context The context.\r
 \r
@@ -116,25 +130,77 @@ HttpTcpReceiveNotifyDpc (
   UINTN                    Length;\r
   EFI_STATUS               Status;\r
   HTTP_PROTOCOL            *HttpInstance;\r
+  BOOLEAN                  UsingIpv6;\r
 \r
   if (Context == NULL) {\r
     return ;\r
   }\r
 \r
   Wrap = (HTTP_TOKEN_WRAP *) Context;\r
-  gBS->CloseEvent (Wrap->TcpWrap.RxToken.CompletionToken.Event);\r
-  if (EFI_ERROR (Wrap->TcpWrap.RxToken.CompletionToken.Status)) {\r
-    return ;\r
-  }\r
-\r
   HttpInstance = Wrap->HttpInstance;\r
+  UsingIpv6    = HttpInstance->LocalAddressIsIPv6;\r
+\r
+  if (UsingIpv6) {\r
+    gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
+    Wrap->TcpWrap.Rx6Token.CompletionToken.Event = NULL;\r
+\r
+    if (EFI_ERROR (Wrap->TcpWrap.Rx6Token.CompletionToken.Status)) {\r
+      DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx6Token.CompletionToken.Status));\r
+      Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
+      gBS->SignalEvent (Wrap->HttpToken->Event);\r
+\r
+      Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
+      if (Item != NULL) {\r
+        NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
+      }\r
+\r
+      FreePool (Wrap);\r
+      Wrap = NULL;\r
+\r
+      return ;\r
+    }\r
+\r
+  } else {\r
+    gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+    Wrap->TcpWrap.Rx4Token.CompletionToken.Event = NULL;\r
+\r
+    if (EFI_ERROR (Wrap->TcpWrap.Rx4Token.CompletionToken.Status)) {\r
+      DEBUG ((EFI_D_ERROR, "HttpTcpReceiveNotifyDpc: %r!\n", Wrap->TcpWrap.Rx4Token.CompletionToken.Status));\r
+      Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
+      gBS->SignalEvent (Wrap->HttpToken->Event);\r
+\r
+      Item = NetMapFindKey (&HttpInstance->RxTokens, Wrap->HttpToken);\r
+      if (Item != NULL) {\r
+        NetMapRemoveItem (&HttpInstance->RxTokens, Item, NULL);\r
+      }\r
+\r
+      FreePool (Wrap);\r
+      Wrap = NULL;\r
+\r
+      return ;\r
+    }\r
+  }\r
 \r
   //\r
   // Check whether we receive a complete HTTP message.\r
   //\r
   ASSERT (HttpInstance->MsgParser != NULL);\r
+  if (UsingIpv6) {\r
+    Length = (UINTN) Wrap->TcpWrap.Rx6Data.FragmentTable[0].FragmentLength;\r
+  } else {\r
+    Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;\r
+  }\r
+\r
+  //\r
+  // Record the CallbackData data.\r
+  //\r
+  HttpInstance->CallbackData.Wrap = (VOID *) Wrap;\r
+  HttpInstance->CallbackData.ParseData = Wrap->HttpToken->Message->Body;\r
+  HttpInstance->CallbackData.ParseDataLength = Length;\r
 \r
-  Length = (UINTN) Wrap->TcpWrap.RxData.FragmentTable[0].FragmentLength;\r
+  //\r
+  // Parse Body with CallbackData data.\r
+  //\r
   Status = HttpParseMessageBody (\r
              HttpInstance->MsgParser,\r
              Length,\r
@@ -158,7 +224,7 @@ HttpTcpReceiveNotifyDpc (
   // We receive part of header of next HTTP msg.\r
   //\r
   if (HttpInstance->NextMsg != NULL) {\r
-    Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg - \r
+    Wrap->HttpToken->Message->BodyLength = HttpInstance->NextMsg -\r
                                            (CHAR8 *) Wrap->HttpToken->Message->Body;\r
     HttpInstance->CacheLen = Length - Wrap->HttpToken->Message->BodyLength;\r
     if (HttpInstance->CacheLen != 0) {\r
@@ -179,7 +245,12 @@ HttpTcpReceiveNotifyDpc (
 \r
 \r
   Wrap->TcpWrap.IsRxDone = TRUE;\r
-  Wrap->HttpToken->Status = Wrap->TcpWrap.RxToken.CompletionToken.Status;\r
+  if (UsingIpv6) {\r
+    Wrap->HttpToken->Status = Wrap->TcpWrap.Rx6Token.CompletionToken.Status;\r
+  } else {\r
+    Wrap->HttpToken->Status = Wrap->TcpWrap.Rx4Token.CompletionToken.Status;\r
+  }\r
+\r
 \r
   gBS->SignalEvent (Wrap->HttpToken->Event);\r
 \r
@@ -187,8 +258,9 @@ HttpTcpReceiveNotifyDpc (
   // Check pending RxTokens and receive the HTTP message.\r
   //\r
   NetMapIterate (&Wrap->HttpInstance->RxTokens, HttpTcpReceive, NULL);\r
-  \r
+\r
   FreePool (Wrap);\r
+  Wrap = NULL;\r
 }\r
 \r
 /**\r
@@ -211,9 +283,8 @@ HttpTcpReceiveNotify (
   QueueDpc (TPL_CALLBACK, HttpTcpReceiveNotifyDpc, Context);\r
 }\r
 \r
-\r
 /**\r
-  Create events for the TCP4 connection token and TCP4 close token.\r
+  Create events for the TCP connection token and TCP close token.\r
 \r
   @param[in]  HttpInstance       Pointer to HTTP_PROTOCOL structure.\r
 \r
@@ -222,11 +293,42 @@ HttpTcpReceiveNotify (
 \r
 **/\r
 EFI_STATUS\r
-HttpCreateTcp4ConnCloseEvent (\r
+HttpCreateTcpConnCloseEvent (\r
   IN  HTTP_PROTOCOL        *HttpInstance\r
   )\r
 {\r
   EFI_STATUS               Status;\r
+\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    //\r
+    // Create events for variuos asynchronous operations.\r
+    //\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpCommonNotify,\r
+                    &HttpInstance->IsTcp4ConnDone,\r
+                    &HttpInstance->Tcp4ConnToken.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ERROR;\r
+    }\r
+\r
+    //\r
+    // Initialize Tcp4CloseToken\r
+    //\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpCommonNotify,\r
+                    &HttpInstance->IsTcp4CloseDone,\r
+                    &HttpInstance->Tcp4CloseToken.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ERROR;\r
+    }\r
+\r
+  } else {\r
     //\r
     // Create events for variuos asynchronous operations.\r
     //\r
@@ -234,66 +336,80 @@ HttpCreateTcp4ConnCloseEvent (
                     EVT_NOTIFY_SIGNAL,\r
                     TPL_NOTIFY,\r
                     HttpCommonNotify,\r
-                    &HttpInstance->IsConnDone,\r
-                    &HttpInstance->ConnToken.CompletionToken.Event\r
+                    &HttpInstance->IsTcp6ConnDone,\r
+                    &HttpInstance->Tcp6ConnToken.CompletionToken.Event\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       goto ERROR;\r
     }\r
 \r
     //\r
-    // Initialize CloseToken\r
+    // Initialize Tcp6CloseToken\r
     //\r
     Status = gBS->CreateEvent (\r
                     EVT_NOTIFY_SIGNAL,\r
                     TPL_NOTIFY,\r
                     HttpCommonNotify,\r
-                    &HttpInstance->IsCloseDone,\r
-                    &HttpInstance->CloseToken.CompletionToken.Event\r
+                    &HttpInstance->IsTcp6CloseDone,\r
+                    &HttpInstance->Tcp6CloseToken.CompletionToken.Event\r
                     );\r
     if (EFI_ERROR (Status)) {\r
       goto ERROR;\r
     }\r
+  }\r
 \r
\r
   return EFI_SUCCESS;\r
 \r
 ERROR:\r
   //\r
   // Error handling\r
   //\r
-  HttpCloseTcp4ConnCloseEvent (HttpInstance);\r
+  HttpCloseTcpConnCloseEvent (HttpInstance);\r
 \r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Close events in the TCP4 connection token and TCP4 close token.\r
+  Close events in the TCP connection token and TCP close token.\r
 \r
   @param[in]  HttpInstance   Pointer to HTTP_PROTOCOL structure.\r
 \r
 **/\r
 VOID\r
-HttpCloseTcp4ConnCloseEvent (\r
+HttpCloseTcpConnCloseEvent (\r
   IN  HTTP_PROTOCOL        *HttpInstance\r
   )\r
 {\r
   ASSERT (HttpInstance != NULL);\r
 \r
-  if (NULL != HttpInstance->ConnToken.CompletionToken.Event) {\r
-    gBS->CloseEvent (HttpInstance->ConnToken.CompletionToken.Event);\r
-    HttpInstance->ConnToken.CompletionToken.Event = NULL;\r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    if (NULL != HttpInstance->Tcp6ConnToken.CompletionToken.Event) {\r
+      gBS->CloseEvent (HttpInstance->Tcp6ConnToken.CompletionToken.Event);\r
+      HttpInstance->Tcp6ConnToken.CompletionToken.Event = NULL;\r
+    }\r
+\r
+    if (NULL != HttpInstance->Tcp6CloseToken.CompletionToken.Event) {\r
+      gBS->CloseEvent(HttpInstance->Tcp6CloseToken.CompletionToken.Event);\r
+      HttpInstance->Tcp6CloseToken.CompletionToken.Event = NULL;\r
+    }\r
+\r
+  } else {\r
+    if (NULL != HttpInstance->Tcp4ConnToken.CompletionToken.Event) {\r
+      gBS->CloseEvent (HttpInstance->Tcp4ConnToken.CompletionToken.Event);\r
+      HttpInstance->Tcp4ConnToken.CompletionToken.Event = NULL;\r
+    }\r
+\r
+    if (NULL != HttpInstance->Tcp4CloseToken.CompletionToken.Event) {\r
+      gBS->CloseEvent(HttpInstance->Tcp4CloseToken.CompletionToken.Event);\r
+      HttpInstance->Tcp4CloseToken.CompletionToken.Event = NULL;\r
+    }\r
   }\r
 \r
-  if (NULL != HttpInstance->CloseToken.CompletionToken.Event) {\r
-    gBS->CloseEvent(HttpInstance->CloseToken.CompletionToken.Event);\r
-    HttpInstance->CloseToken.CompletionToken.Event = NULL;\r
-  }  \r
 }\r
 \r
 /**\r
-  Create event for the TCP4 transmit token.\r
+  Create event for the TCP transmit token.\r
 \r
   @param[in]  Wrap               Point to HTTP token's wrap data.\r
 \r
@@ -302,7 +418,7 @@ HttpCloseTcp4ConnCloseEvent (
 \r
 **/\r
 EFI_STATUS\r
-HttpCreateTcp4TxEvent (\r
+HttpCreateTcpTxEvent (\r
   IN  HTTP_TOKEN_WRAP      *Wrap\r
   )\r
 {\r
@@ -313,28 +429,49 @@ HttpCreateTcp4TxEvent (
   HttpInstance = Wrap->HttpInstance;\r
   TcpWrap      = &Wrap->TcpWrap;\r
 \r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  HttpTcpTransmitNotify,\r
-                  Wrap,\r
-                  &TcpWrap->TxToken.CompletionToken.Event\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpTcpTransmitNotify,\r
+                    Wrap,\r
+                    &TcpWrap->Tx4Token.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    TcpWrap->Tx4Data.Push = TRUE;\r
+    TcpWrap->Tx4Data.Urgent = FALSE;\r
+    TcpWrap->Tx4Data.FragmentCount = 1;\r
+    TcpWrap->Tx4Token.Packet.TxData = &Wrap->TcpWrap.Tx4Data;\r
+    TcpWrap->Tx4Token.CompletionToken.Status = EFI_NOT_READY;\r
+\r
+  } else {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpTcpTransmitNotify,\r
+                    Wrap,\r
+                    &TcpWrap->Tx6Token.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    TcpWrap->Tx6Data.Push   = TRUE;\r
+    TcpWrap->Tx6Data.Urgent = FALSE;\r
+    TcpWrap->Tx6Data.FragmentCount  = 1;\r
+    TcpWrap->Tx6Token.Packet.TxData = &Wrap->TcpWrap.Tx6Data;\r
+    TcpWrap->Tx6Token.CompletionToken.Status =EFI_NOT_READY;\r
 \r
-  TcpWrap->TxData.Push = TRUE;\r
-  TcpWrap->TxData.Urgent = FALSE;\r
-  TcpWrap->TxData.FragmentCount = 1;\r
-  TcpWrap->TxToken.Packet.TxData = &Wrap->TcpWrap.TxData;\r
-  TcpWrap->TxToken.CompletionToken.Status = EFI_NOT_READY;\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Create event for the TCP4 receive token which is used to receive HTTP header.\r
+  Create event for the TCP receive token which is used to receive HTTP header.\r
 \r
   @param[in]  HttpInstance       Pointer to HTTP_PROTOCOL structure.\r
 \r
@@ -343,33 +480,52 @@ HttpCreateTcp4TxEvent (
 \r
 **/\r
 EFI_STATUS\r
-HttpCreateTcp4RxEventForHeader (\r
+HttpCreateTcpRxEventForHeader (\r
   IN  HTTP_PROTOCOL        *HttpInstance\r
   )\r
 {\r
   EFI_STATUS               Status;\r
 \r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpCommonNotify,\r
+                    &HttpInstance->IsRxDone,\r
+                    &HttpInstance->Rx4Token.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    HttpInstance->Rx4Data.FragmentCount = 1;\r
+    HttpInstance->Rx4Token.Packet.RxData = &HttpInstance->Rx4Data;\r
+    HttpInstance->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
+\r
+  } else {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpCommonNotify,\r
+                    &HttpInstance->IsRxDone,\r
+                    &HttpInstance->Rx6Token.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+\r
+    HttpInstance->Rx6Data.FragmentCount  =1;\r
+    HttpInstance->Rx6Token.Packet.RxData = &HttpInstance->Rx6Data;\r
+    HttpInstance->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
 \r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  HttpCommonNotify,\r
-                  &HttpInstance->IsRxDone,\r
-                  &HttpInstance->RxToken.CompletionToken.Event\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
   }\r
 \r
-  HttpInstance->RxData.FragmentCount = 1;\r
-  HttpInstance->RxToken.Packet.RxData = &HttpInstance->RxData;\r
-  HttpInstance->RxToken.CompletionToken.Status = EFI_NOT_READY;\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Create event for the TCP4 receive token which is used to receive HTTP body.\r
+  Create event for the TCP receive token which is used to receive HTTP body.\r
 \r
   @param[in]  Wrap               Point to HTTP token's wrap data.\r
 \r
@@ -378,8 +534,8 @@ HttpCreateTcp4RxEventForHeader (
 \r
 **/\r
 EFI_STATUS\r
-HttpCreateTcp4RxEvent (\r
-  IN  HTTP_TOKEN_WRAP      *Wrap \r
+HttpCreateTcpRxEvent (\r
+  IN  HTTP_TOKEN_WRAP      *Wrap\r
   )\r
 {\r
   EFI_STATUS               Status;\r
@@ -388,87 +544,206 @@ HttpCreateTcp4RxEvent (
 \r
   HttpInstance = Wrap->HttpInstance;\r
   TcpWrap      = &Wrap->TcpWrap;\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpTcpReceiveNotify,\r
+                    Wrap,\r
+                    &TcpWrap->Rx4Token.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
 \r
-  Status = gBS->CreateEvent (\r
-                  EVT_NOTIFY_SIGNAL,\r
-                  TPL_NOTIFY,\r
-                  HttpTcpReceiveNotify,\r
-                  Wrap,\r
-                  &TcpWrap->RxToken.CompletionToken.Event\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+    TcpWrap->Rx4Data.FragmentCount = 1;\r
+    TcpWrap->Rx4Token.Packet.RxData = &Wrap->TcpWrap.Rx4Data;\r
+    TcpWrap->Rx4Token.CompletionToken.Status = EFI_NOT_READY;\r
+\r
+  } else {\r
+    Status = gBS->CreateEvent (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_NOTIFY,\r
+                    HttpTcpReceiveNotify,\r
+                    Wrap,\r
+                    &TcpWrap->Rx6Token.CompletionToken.Event\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
 \r
-  TcpWrap->RxData.FragmentCount = 1;\r
-  TcpWrap->RxToken.Packet.RxData = &Wrap->TcpWrap.RxData;\r
-  TcpWrap->RxToken.CompletionToken.Status = EFI_NOT_READY;\r
+    TcpWrap->Rx6Data.FragmentCount = 1;\r
+    TcpWrap->Rx6Token.Packet.RxData = &Wrap->TcpWrap.Rx6Data;\r
+    TcpWrap->Rx6Token.CompletionToken.Status = EFI_NOT_READY;\r
+  }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Close Events for Tcp Receive Tokens for HTTP body and HTTP header.\r
+\r
+  @param[in]  Wrap               Pointer to HTTP token's wrap data.\r
+\r
+**/\r
+VOID\r
+HttpCloseTcpRxEvent (\r
+  IN  HTTP_TOKEN_WRAP      *Wrap\r
+  )\r
+{\r
+  HTTP_PROTOCOL            *HttpInstance;\r
+\r
+  ASSERT (Wrap != NULL);\r
+  HttpInstance   = Wrap->HttpInstance;\r
+\r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    if (Wrap->TcpWrap.Rx6Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Rx6Token.CompletionToken.Event);\r
+    }\r
+\r
+    if (HttpInstance->Rx6Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (HttpInstance->Rx6Token.CompletionToken.Event);\r
+      HttpInstance->Rx6Token.CompletionToken.Event = NULL;\r
+    }\r
+  } else {\r
+    if (Wrap->TcpWrap.Rx4Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Wrap->TcpWrap.Rx4Token.CompletionToken.Event);\r
+    }\r
+\r
+    if (HttpInstance->Rx4Token.CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (HttpInstance->Rx4Token.CompletionToken.Event);\r
+      HttpInstance->Rx4Token.CompletionToken.Event = NULL;\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Intiialize the HTTP_PROTOCOL structure to the unconfigured state.\r
 \r
-  @param[in]       HttpSb               The HTTP service private instance.\r
   @param[in, out]  HttpInstance         Pointer to HTTP_PROTOCOL structure.\r
+  @param[in]       IpVersion            Indicate us TCP4 protocol or TCP6 protocol.\r
 \r
-  @retval EFI_SUCCESS       HTTP_PROTOCOL structure is initialized successfully.                                          \r
+  @retval EFI_SUCCESS       HTTP_PROTOCOL structure is initialized successfully.\r
   @retval Others            Other error as indicated.\r
 \r
 **/\r
 EFI_STATUS\r
 HttpInitProtocol (\r
-  IN     HTTP_SERVICE            *HttpSb,\r
-  IN OUT HTTP_PROTOCOL           *HttpInstance\r
+  IN OUT HTTP_PROTOCOL           *HttpInstance,\r
+  IN     BOOLEAN                 IpVersion\r
   )\r
 {\r
   EFI_STATUS                     Status;\r
   VOID                           *Interface;\r
+  BOOLEAN                        UsingIpv6;\r
 \r
-  ASSERT ((HttpSb != NULL) && (HttpInstance != NULL));\r
+  ASSERT (HttpInstance != NULL);\r
+  UsingIpv6 = IpVersion;\r
 \r
-  HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;\r
-  CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));\r
-  HttpInstance->Service = HttpSb;\r
+  if (!UsingIpv6) {\r
+    //\r
+    // Create TCP4 child.\r
+    //\r
+    Status = NetLibCreateServiceChild (\r
+               HttpInstance->Service->ControllerHandle,\r
+               HttpInstance->Service->Ip4DriverBindingHandle,\r
+               &gEfiTcp4ServiceBindingProtocolGuid,\r
+               &HttpInstance->Tcp4ChildHandle\r
+               );\r
 \r
-  //\r
-  // Create TCP child.\r
-  //\r
-  Status = NetLibCreateServiceChild (\r
-             HttpInstance->Service->ControllerHandle,\r
-             HttpInstance->Service->ImageHandle,\r
-             &gEfiTcp4ServiceBindingProtocolGuid,\r
-             &HttpInstance->TcpChildHandle\r
-             );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
+    Status = gBS->OpenProtocol (\r
+                    HttpInstance->Tcp4ChildHandle,\r
+                    &gEfiTcp4ProtocolGuid,\r
+                    (VOID **) &Interface,\r
+                    HttpInstance->Service->Ip4DriverBindingHandle,\r
+                    HttpInstance->Service->ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
 \r
-  Status = gBS->OpenProtocol (\r
-                  HttpInstance->TcpChildHandle,\r
-                  &gEfiTcp4ProtocolGuid,\r
-                  (VOID **) &Interface,\r
-                  HttpInstance->Service->ImageHandle,\r
-                  HttpInstance->Service->ControllerHandle,\r
-                  EFI_OPEN_PROTOCOL_BY_DRIVER\r
-                  );\r
-                  \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
 \r
-  Status = gBS->OpenProtocol (\r
-                  HttpInstance->TcpChildHandle,\r
-                  &gEfiTcp4ProtocolGuid,\r
-                  (VOID **) &HttpInstance->Tcp4,\r
-                  HttpInstance->Service->ImageHandle,\r
-                  HttpInstance->Handle,\r
-                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
-                  );\r
-  if (EFI_ERROR(Status)) {\r
-    goto ON_ERROR;\r
+    Status = gBS->OpenProtocol (\r
+                    HttpInstance->Tcp4ChildHandle,\r
+                    &gEfiTcp4ProtocolGuid,\r
+                    (VOID **) &HttpInstance->Tcp4,\r
+                    HttpInstance->Service->Ip4DriverBindingHandle,\r
+                    HttpInstance->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+    if (EFI_ERROR(Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    HttpInstance->Service->Tcp4ChildHandle,\r
+                    &gEfiTcp4ProtocolGuid,\r
+                    (VOID **) &Interface,\r
+                    HttpInstance->Service->Ip4DriverBindingHandle,\r
+                    HttpInstance->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+    if (EFI_ERROR(Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+  } else {\r
+    //\r
+    // Create TCP6 Child.\r
+    //\r
+    Status = NetLibCreateServiceChild (\r
+               HttpInstance->Service->ControllerHandle,\r
+               HttpInstance->Service->Ip6DriverBindingHandle,\r
+               &gEfiTcp6ServiceBindingProtocolGuid,\r
+               &HttpInstance->Tcp6ChildHandle\r
+               );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    HttpInstance->Tcp6ChildHandle,\r
+                    &gEfiTcp6ProtocolGuid,\r
+                    (VOID **) &Interface,\r
+                    HttpInstance->Service->Ip6DriverBindingHandle,\r
+                    HttpInstance->Service->ControllerHandle,\r
+                    EFI_OPEN_PROTOCOL_BY_DRIVER\r
+                    );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    HttpInstance->Tcp6ChildHandle,\r
+                    &gEfiTcp6ProtocolGuid,\r
+                    (VOID **) &HttpInstance->Tcp6,\r
+                    HttpInstance->Service->Ip6DriverBindingHandle,\r
+                    HttpInstance->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+\r
+    if (EFI_ERROR(Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    Status = gBS->OpenProtocol (\r
+                    HttpInstance->Service->Tcp6ChildHandle,\r
+                    &gEfiTcp6ProtocolGuid,\r
+                    (VOID **) &Interface,\r
+                    HttpInstance->Service->Ip6DriverBindingHandle,\r
+                    HttpInstance->Handle,\r
+                    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+                    );\r
+\r
+    if (EFI_ERROR(Status)) {\r
+      goto ON_ERROR;\r
+    }\r
   }\r
 \r
   HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN);\r
@@ -477,38 +752,76 @@ HttpInitProtocol (
     goto ON_ERROR;\r
   }\r
 \r
-  NetMapInit (&HttpInstance->TxTokens);\r
-  NetMapInit (&HttpInstance->RxTokens);\r
-\r
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
-  \r
-  if (HttpInstance->TcpChildHandle != NULL) {\r
+\r
+  if (HttpInstance->Tcp4ChildHandle != NULL) {\r
     gBS->CloseProtocol (\r
-           HttpInstance->TcpChildHandle,\r
+           HttpInstance->Tcp4ChildHandle,\r
            &gEfiTcp4ProtocolGuid,\r
-           HttpInstance->Service->ImageHandle,\r
+           HttpInstance->Service->Ip4DriverBindingHandle,\r
            HttpInstance->Service->ControllerHandle\r
            );\r
 \r
     gBS->CloseProtocol (\r
-           HttpInstance->TcpChildHandle,\r
+           HttpInstance->Tcp4ChildHandle,\r
            &gEfiTcp4ProtocolGuid,\r
-           HttpInstance->Service->ImageHandle,\r
+           HttpInstance->Service->Ip4DriverBindingHandle,\r
            HttpInstance->Handle\r
            );\r
-    \r
+\r
     NetLibDestroyServiceChild (\r
       HttpInstance->Service->ControllerHandle,\r
-      HttpInstance->Service->ImageHandle,\r
+      HttpInstance->Service->Ip4DriverBindingHandle,\r
       &gEfiTcp4ServiceBindingProtocolGuid,\r
-      HttpInstance->TcpChildHandle\r
+      HttpInstance->Tcp4ChildHandle\r
       );\r
   }\r
 \r
-  return Status;\r
-  \r
+  if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Service->Tcp4ChildHandle,\r
+           &gEfiTcp4ProtocolGuid,\r
+           HttpInstance->Service->Ip4DriverBindingHandle,\r
+           HttpInstance->Handle\r
+           );\r
+  }\r
+\r
+  if (HttpInstance->Tcp6ChildHandle != NULL) {\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Tcp6ChildHandle,\r
+           &gEfiTcp6ProtocolGuid,\r
+           HttpInstance->Service->Ip6DriverBindingHandle,\r
+           HttpInstance->Service->ControllerHandle\r
+           );\r
+\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Tcp6ChildHandle,\r
+           &gEfiTcp6ProtocolGuid,\r
+           HttpInstance->Service->Ip6DriverBindingHandle,\r
+           HttpInstance->Handle\r
+           );\r
+\r
+    NetLibDestroyServiceChild (\r
+      HttpInstance->Service->ControllerHandle,\r
+      HttpInstance->Service->Ip6DriverBindingHandle,\r
+      &gEfiTcp6ServiceBindingProtocolGuid,\r
+      HttpInstance->Tcp6ChildHandle\r
+      );\r
+  }\r
+\r
+  if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Service->Tcp6ChildHandle,\r
+           &gEfiTcp6ProtocolGuid,\r
+           HttpInstance->Service->Ip6DriverBindingHandle,\r
+           HttpInstance->Handle\r
+           );\r
+  }\r
+\r
+  return EFI_UNSUPPORTED;\r
+\r
 }\r
 \r
 /**\r
@@ -523,8 +836,13 @@ HttpCleanProtocol (
   )\r
 {\r
   HttpCloseConnection (HttpInstance);\r
-  \r
-  HttpCloseTcp4ConnCloseEvent (HttpInstance);\r
+\r
+  HttpCloseTcpConnCloseEvent (HttpInstance);\r
+\r
+  if (HttpInstance->TimeoutEvent != NULL) {\r
+    gBS->CloseEvent (HttpInstance->TimeoutEvent);\r
+    HttpInstance->TimeoutEvent = NULL;\r
+  }\r
 \r
   if (HttpInstance->CacheBody != NULL) {\r
     FreePool (HttpInstance->CacheBody);\r
@@ -550,39 +868,89 @@ HttpCleanProtocol (
   NetMapClean (&HttpInstance->TxTokens);\r
   NetMapClean (&HttpInstance->RxTokens);\r
 \r
-  if (HttpInstance->TcpChildHandle != NULL) {\r
+  if (HttpInstance->TlsSb != NULL && HttpInstance->TlsChildHandle != NULL) {\r
+    //\r
+    // Destroy the TLS instance.\r
+    //\r
+    HttpInstance->TlsSb->DestroyChild (HttpInstance->TlsSb, HttpInstance->TlsChildHandle);\r
+  }\r
+\r
+  if (HttpInstance->Tcp4ChildHandle != NULL) {\r
     gBS->CloseProtocol (\r
-           HttpInstance->TcpChildHandle,\r
+           HttpInstance->Tcp4ChildHandle,\r
            &gEfiTcp4ProtocolGuid,\r
-           HttpInstance->Service->ImageHandle,\r
+           HttpInstance->Service->Ip4DriverBindingHandle,\r
            HttpInstance->Service->ControllerHandle\r
            );\r
 \r
     gBS->CloseProtocol (\r
-           HttpInstance->TcpChildHandle,\r
+           HttpInstance->Tcp4ChildHandle,\r
            &gEfiTcp4ProtocolGuid,\r
-           HttpInstance->Service->ImageHandle,\r
+           HttpInstance->Service->Ip4DriverBindingHandle,\r
            HttpInstance->Handle\r
            );\r
-    \r
+\r
     NetLibDestroyServiceChild (\r
       HttpInstance->Service->ControllerHandle,\r
-      HttpInstance->Service->ImageHandle,\r
+      HttpInstance->Service->Ip4DriverBindingHandle,\r
       &gEfiTcp4ServiceBindingProtocolGuid,\r
-      HttpInstance->TcpChildHandle\r
+      HttpInstance->Tcp4ChildHandle\r
       );\r
   }\r
-}\r
-\r
-/**\r
-  Establish TCP connection with HTTP server.\r
 \r
-  @param[in]  HttpInstance       The HTTP instance private data.\r
+  if (HttpInstance->Service->Tcp4ChildHandle != NULL) {\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Service->Tcp4ChildHandle,\r
+           &gEfiTcp4ProtocolGuid,\r
+           HttpInstance->Service->Ip4DriverBindingHandle,\r
+           HttpInstance->Handle\r
+           );\r
+  }\r
 \r
-  @retval EFI_SUCCESS            The TCP connection is established.\r
-  @retval Others                 Other error as indicated.\r
+  if (HttpInstance->Tcp6ChildHandle != NULL) {\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Tcp6ChildHandle,\r
+           &gEfiTcp6ProtocolGuid,\r
+           HttpInstance->Service->Ip6DriverBindingHandle,\r
+           HttpInstance->Service->ControllerHandle\r
+           );\r
 \r
-**/\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Tcp6ChildHandle,\r
+           &gEfiTcp6ProtocolGuid,\r
+           HttpInstance->Service->Ip6DriverBindingHandle,\r
+           HttpInstance->Handle\r
+           );\r
+\r
+    NetLibDestroyServiceChild (\r
+      HttpInstance->Service->ControllerHandle,\r
+      HttpInstance->Service->Ip6DriverBindingHandle,\r
+      &gEfiTcp6ServiceBindingProtocolGuid,\r
+      HttpInstance->Tcp6ChildHandle\r
+      );\r
+  }\r
+\r
+  if (HttpInstance->Service->Tcp6ChildHandle != NULL) {\r
+    gBS->CloseProtocol (\r
+           HttpInstance->Service->Tcp6ChildHandle,\r
+           &gEfiTcp6ProtocolGuid,\r
+           HttpInstance->Service->Ip6DriverBindingHandle,\r
+           HttpInstance->Handle\r
+           );\r
+  }\r
+\r
+  TlsCloseTxRxEvent (HttpInstance);\r
+}\r
+\r
+/**\r
+  Establish TCP connection with HTTP server.\r
+\r
+  @param[in]  HttpInstance       The HTTP instance private data.\r
+\r
+  @retval EFI_SUCCESS            The TCP connection is established.\r
+  @retval Others                 Other error as indicated.\r
+\r
+**/\r
 EFI_STATUS\r
 HttpCreateConnection (\r
   IN  HTTP_PROTOCOL        *HttpInstance\r
@@ -590,26 +958,39 @@ HttpCreateConnection (
 {\r
   EFI_STATUS                    Status;\r
 \r
-  //\r
-  // Create events for variuos asynchronous operations.\r
-  //\r
-  HttpInstance->IsConnDone = FALSE;\r
-\r
   //\r
   // Connect to Http server\r
   //\r
-  HttpInstance->ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
-  Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->ConnToken);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
-    return Status;\r
-  }\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    HttpInstance->IsTcp4ConnDone = FALSE;\r
+    HttpInstance->Tcp4ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
+    Status = HttpInstance->Tcp4->Connect (HttpInstance->Tcp4, &HttpInstance->Tcp4ConnToken);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp4->Connect() = %r\n", Status));\r
+      return Status;\r
+    }\r
 \r
-  while (!HttpInstance->IsConnDone) {\r
-    HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
-  }\r
+    while (!HttpInstance->IsTcp4ConnDone) {\r
+      HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+    }\r
 \r
-  Status = HttpInstance->ConnToken.CompletionToken.Status;\r
+    Status = HttpInstance->Tcp4ConnToken.CompletionToken.Status;\r
+\r
+  } else {\r
+    HttpInstance->IsTcp6ConnDone = FALSE;\r
+    HttpInstance->Tcp6ConnToken.CompletionToken.Status = EFI_NOT_READY;\r
+    Status = HttpInstance->Tcp6->Connect (HttpInstance->Tcp6, &HttpInstance->Tcp6ConnToken);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "HttpCreateConnection: Tcp6->Connect() = %r\n", Status));\r
+      return Status;\r
+    }\r
+\r
+    while(!HttpInstance->IsTcp6ConnDone) {\r
+      HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+    }\r
+\r
+    Status = HttpInstance->Tcp6ConnToken.CompletionToken.Status;\r
+  }\r
 \r
   if (!EFI_ERROR (Status)) {\r
     HttpInstance->State = HTTP_STATE_TCP_CONNECTED;\r
@@ -635,17 +1016,32 @@ HttpCloseConnection (
   EFI_STATUS                Status;\r
 \r
   if (HttpInstance->State == HTTP_STATE_TCP_CONNECTED) {\r
-    HttpInstance->CloseToken.AbortOnClose = TRUE;\r
-    HttpInstance->IsCloseDone             = FALSE;\r
-    \r
-    Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->CloseToken);\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
 \r
-    while (!HttpInstance->IsCloseDone) {\r
-      HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+    if (HttpInstance->LocalAddressIsIPv6) {\r
+      HttpInstance->Tcp6CloseToken.AbortOnClose = TRUE;\r
+      HttpInstance->IsTcp6CloseDone             = FALSE;\r
+      Status = HttpInstance->Tcp6->Close (HttpInstance->Tcp6, &HttpInstance->Tcp6CloseToken);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      while (!HttpInstance->IsTcp6CloseDone) {\r
+        HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);\r
+      }\r
+\r
+    } else {\r
+      HttpInstance->Tcp4CloseToken.AbortOnClose = TRUE;\r
+      HttpInstance->IsTcp4CloseDone             = FALSE;\r
+      Status = HttpInstance->Tcp4->Close (HttpInstance->Tcp4, &HttpInstance->Tcp4CloseToken);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+\r
+      while (!HttpInstance->IsTcp4CloseDone) {\r
+        HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);\r
+      }\r
     }\r
+\r
   }\r
 \r
   HttpInstance->State = HTTP_STATE_TCP_CLOSED;\r
@@ -672,15 +1068,13 @@ HttpConfigureTcp4 (
   EFI_TCP4_CONFIG_DATA       *Tcp4CfgData;\r
   EFI_TCP4_ACCESS_POINT      *Tcp4AP;\r
   EFI_TCP4_OPTION            *Tcp4Option;\r
-  HTTP_TCP_TOKEN_WRAP        *TcpWrap;\r
 \r
   ASSERT (HttpInstance != NULL);\r
-  TcpWrap = &Wrap->TcpWrap;\r
 \r
 \r
   Tcp4CfgData = &HttpInstance->Tcp4CfgData;\r
   ZeroMem (Tcp4CfgData, sizeof (EFI_TCP4_CONFIG_DATA));\r
-  \r
+\r
   Tcp4CfgData->TypeOfService = HTTP_TOS_DEAULT;\r
   Tcp4CfgData->TimeToLive    = HTTP_TTL_DEAULT;\r
   Tcp4CfgData->ControlOption = &HttpInstance->Tcp4Option;\r
@@ -691,7 +1085,7 @@ HttpConfigureTcp4 (
     IP4_COPY_ADDRESS (&Tcp4AP->StationAddress, &HttpInstance->IPv4Node.LocalAddress);\r
     IP4_COPY_ADDRESS (&Tcp4AP->SubnetMask, &HttpInstance->IPv4Node.LocalSubnet);\r
   }\r
-  \r
+\r
   Tcp4AP->StationPort = HttpInstance->IPv4Node.LocalPort;\r
   Tcp4AP->RemotePort  = HttpInstance->RemotePort;\r
   Tcp4AP->ActiveFlag  = TRUE;\r
@@ -716,12 +1110,82 @@ HttpConfigureTcp4 (
     return Status;\r
   }\r
 \r
-  Status = HttpCreateTcp4ConnCloseEvent (HttpInstance);\r
+  Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = HttpCreateTcpTxEvent (Wrap);\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Configure TCP6 protocol child.\r
+\r
+  @param[in]  HttpInstance       The HTTP instance private data.\r
+  @param[in]  Wrap               The HTTP token's wrap data.\r
+\r
+  @retval EFI_SUCCESS            The TCP6 protocol child is configured.\r
+  @retval Others                 Other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpConfigureTcp6 (\r
+  IN  HTTP_PROTOCOL        *HttpInstance,\r
+  IN  HTTP_TOKEN_WRAP      *Wrap\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  EFI_TCP6_CONFIG_DATA     *Tcp6CfgData;\r
+  EFI_TCP6_ACCESS_POINT    *Tcp6Ap;\r
+  EFI_TCP6_OPTION          *Tcp6Option;\r
+\r
+  ASSERT (HttpInstance != NULL);\r
+\r
+  Tcp6CfgData = &HttpInstance->Tcp6CfgData;\r
+  ZeroMem (Tcp6CfgData, sizeof (EFI_TCP6_CONFIG_DATA));\r
+\r
+  Tcp6CfgData->TrafficClass  = 0;\r
+  Tcp6CfgData->HopLimit      = 255;\r
+  Tcp6CfgData->ControlOption = &HttpInstance->Tcp6Option;\r
+\r
+  Tcp6Ap  = &Tcp6CfgData->AccessPoint;\r
+  Tcp6Ap->ActiveFlag  = TRUE;\r
+  Tcp6Ap->StationPort = HttpInstance->Ipv6Node.LocalPort;\r
+  Tcp6Ap->RemotePort  = HttpInstance->RemotePort;\r
+  IP6_COPY_ADDRESS (&Tcp6Ap->StationAddress, &HttpInstance->Ipv6Node.LocalAddress);\r
+  IP6_COPY_ADDRESS (&Tcp6Ap->RemoteAddress , &HttpInstance->RemoteIpv6Addr);\r
+\r
+  Tcp6Option = Tcp6CfgData->ControlOption;\r
+  Tcp6Option->ReceiveBufferSize  = HTTP_BUFFER_SIZE_DEAULT;\r
+  Tcp6Option->SendBufferSize     = HTTP_BUFFER_SIZE_DEAULT;\r
+  Tcp6Option->MaxSynBackLog      = HTTP_MAX_SYN_BACK_LOG;\r
+  Tcp6Option->ConnectionTimeout  = HTTP_CONNECTION_TIMEOUT;\r
+  Tcp6Option->DataRetries        = HTTP_DATA_RETRIES;\r
+  Tcp6Option->FinTimeout         = HTTP_FIN_TIMEOUT;\r
+  Tcp6Option->KeepAliveProbes    = HTTP_KEEP_ALIVE_PROBES;\r
+  Tcp6Option->KeepAliveTime      = HTTP_KEEP_ALIVE_TIME;\r
+  Tcp6Option->KeepAliveInterval  = HTTP_KEEP_ALIVE_INTERVAL;\r
+  Tcp6Option->EnableNagle        = TRUE;\r
+\r
+  Status = HttpInstance->Tcp6->Configure (HttpInstance->Tcp6, Tcp6CfgData);\r
+  if (EFI_ERROR (Status)) {\r
+    DEBUG ((EFI_D_ERROR, "HttpConfigureTcp6 - %r\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  Status = HttpCreateTcpConnCloseEvent (HttpInstance);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
 \r
-  Status = HttpCreateTcp4TxEvent (Wrap);\r
+  Status = HttpCreateTcpTxEvent (Wrap);\r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
@@ -729,10 +1193,12 @@ HttpConfigureTcp4 (
   HttpInstance->State = HTTP_STATE_TCP_CONFIGED;\r
 \r
   return EFI_SUCCESS;\r
+\r
 }\r
 \r
 /**\r
-  Check existing TCP connection, if in error state, receover TCP4 connection.\r
+  Check existing TCP connection, if in error state, recover TCP4 connection. Then,\r
+  connect one TLS session if required.\r
 \r
   @param[in]  HttpInstance       The HTTP instance private data.\r
 \r
@@ -750,13 +1216,13 @@ HttpConnectTcp4 (
   EFI_TCP4_CONNECTION_STATE Tcp4State;\r
 \r
 \r
-  if (HttpInstance->State != HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
+  if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp4 == NULL) {\r
     return EFI_NOT_READY;\r
   }\r
 \r
   Status = HttpInstance->Tcp4->GetModeData(\r
-                                 HttpInstance->Tcp4, \r
-                                 &Tcp4State, \r
+                                 HttpInstance->Tcp4,\r
+                                 &Tcp4State,\r
                                  NULL,\r
                                  NULL,\r
                                  NULL,\r
@@ -767,15 +1233,230 @@ HttpConnectTcp4 (
     return Status;\r
   }\r
 \r
-  if (Tcp4State > Tcp4StateEstablished) {\r
+  if (Tcp4State == Tcp4StateEstablished) {\r
+    return EFI_SUCCESS;\r
+  } else if (Tcp4State > Tcp4StateEstablished ) {\r
     HttpCloseConnection(HttpInstance);\r
-  }  \r
+  }\r
+\r
+  Status = HttpCreateConnection (HttpInstance);\r
+  if (EFI_ERROR(Status)){\r
+    DEBUG ((EFI_D_ERROR, "Tcp4 Connection fail - %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Tls session connection.\r
+  //\r
+  if (HttpInstance->UseHttps) {\r
+    if (HttpInstance->TimeoutEvent == NULL) {\r
+      //\r
+      // Create TimeoutEvent for TLS connection.\r
+      //\r
+      Status = gBS->CreateEvent (\r
+                      EVT_TIMER,\r
+                      TPL_CALLBACK,\r
+                      NULL,\r
+                      NULL,\r
+                      &HttpInstance->TimeoutEvent\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        TlsCloseTxRxEvent (HttpInstance);\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Start the timer, and wait Timeout seconds for connection.\r
+    //\r
+    Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
+    if (EFI_ERROR (Status)) {\r
+      TlsCloseTxRxEvent (HttpInstance);\r
+      return Status;\r
+    }\r
+\r
+    Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
+\r
+    gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      TlsCloseTxRxEvent (HttpInstance);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Check existing TCP connection, if in error state, recover TCP6 connection. Then,\r
+  connect one TLS session if required.\r
+\r
+  @param[in]  HttpInstance       The HTTP instance private data.\r
+\r
+  @retval EFI_SUCCESS            The TCP connection is established.\r
+  @retval EFI_NOT_READY          TCP6 protocol child is not created or configured.\r
+  @retval Others                 Other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpConnectTcp6 (\r
+  IN  HTTP_PROTOCOL        *HttpInstance\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  EFI_TCP6_CONNECTION_STATE Tcp6State;\r
+\r
+  if (HttpInstance->State < HTTP_STATE_TCP_CONFIGED || HttpInstance->Tcp6 == NULL) {\r
+    return EFI_NOT_READY;\r
+  }\r
+\r
+  Status = HttpInstance->Tcp6->GetModeData (\r
+                                 HttpInstance->Tcp6,\r
+                                 &Tcp6State,\r
+                                 NULL,\r
+                                 NULL,\r
+                                 NULL,\r
+                                 NULL\r
+                                 );\r
+\r
+  if (EFI_ERROR(Status)){\r
+     DEBUG ((EFI_D_ERROR, "Tcp6 GetModeData fail - %x\n", Status));\r
+     return Status;\r
+  }\r
+\r
+  if (Tcp6State == Tcp6StateEstablished) {\r
+    return EFI_SUCCESS;\r
+  } else if (Tcp6State > Tcp6StateEstablished ) {\r
+    HttpCloseConnection(HttpInstance);\r
+  }\r
+\r
+  Status = HttpCreateConnection (HttpInstance);\r
+  if (EFI_ERROR(Status)){\r
+    DEBUG ((EFI_D_ERROR, "Tcp6 Connection fail - %x\n", Status));\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Tls session connection.\r
+  //\r
+  if (HttpInstance->UseHttps) {\r
+    if (HttpInstance->TimeoutEvent == NULL) {\r
+      //\r
+      // Create TimeoutEvent for TLS connection.\r
+      //\r
+      Status = gBS->CreateEvent (\r
+                      EVT_TIMER,\r
+                      TPL_CALLBACK,\r
+                      NULL,\r
+                      NULL,\r
+                      &HttpInstance->TimeoutEvent\r
+                      );\r
+      if (EFI_ERROR (Status)) {\r
+        TlsCloseTxRxEvent (HttpInstance);\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Start the timer, and wait Timeout seconds for connection.\r
+    //\r
+    Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative, HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);\r
+    if (EFI_ERROR (Status)) {\r
+      TlsCloseTxRxEvent (HttpInstance);\r
+      return Status;\r
+    }\r
+\r
+    Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);\r
+\r
+    gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      TlsCloseTxRxEvent (HttpInstance);\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Initialize Http session.\r
+\r
+  @param[in]  HttpInstance       The HTTP instance private data.\r
+  @param[in]  Wrap               The HTTP token's wrap data.\r
+  @param[in]  Configure          The Flag indicates whether need to initialize session.\r
+  @param[in]  TlsConfigure       The Flag indicates whether it's the new Tls session.\r
+\r
+  @retval EFI_SUCCESS            The initialization of session is done.\r
+  @retval Others                 Other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpInitSession (\r
+  IN  HTTP_PROTOCOL    *HttpInstance,\r
+  IN  HTTP_TOKEN_WRAP  *Wrap,\r
+  IN  BOOLEAN          Configure,\r
+  IN  BOOLEAN          TlsConfigure\r
+  )\r
+{\r
+  EFI_STATUS           Status;\r
+  ASSERT (HttpInstance != NULL);\r
+\r
+  //\r
+  // Configure Tls session.\r
+  //\r
+  if (TlsConfigure) {\r
+    Status = TlsConfigureSession (HttpInstance);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    //\r
+    // Configure TCP instance.\r
+    //\r
+    if (Configure) {\r
+      Status = HttpConfigureTcp4 (HttpInstance, Wrap);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Connect TCP.\r
+    //\r
+    Status = HttpConnectTcp4 (HttpInstance);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  } else {\r
+    //\r
+    // Configure TCP instance.\r
+    //\r
+    if (Configure) {\r
+      Status = HttpConfigureTcp6 (HttpInstance, Wrap);\r
+      if (EFI_ERROR (Status)) {\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Connect TCP.\r
+    //\r
+    Status = HttpConnectTcp6 (HttpInstance);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
 \r
-  return HttpCreateConnection (HttpInstance);\r
 }\r
 \r
 /**\r
-  Send the HTTP message through TCP4.\r
+  Send the HTTP or HTTPS message through TCP4 or TCP6.\r
 \r
   @param[in]  HttpInstance       The HTTP instance private data.\r
   @param[in]  Wrap               The HTTP token's wrap data.\r
@@ -787,7 +1468,7 @@ HttpConnectTcp4 (
 \r
 **/\r
 EFI_STATUS\r
-HttpTransmitTcp4 (\r
+HttpTransmitTcp (\r
   IN  HTTP_PROTOCOL    *HttpInstance,\r
   IN  HTTP_TOKEN_WRAP  *Wrap,\r
   IN  UINT8            *TxString,\r
@@ -795,131 +1476,162 @@ HttpTransmitTcp4 (
   )\r
 {\r
   EFI_STATUS                    Status;\r
-  EFI_TCP4_IO_TOKEN             *TxToken;\r
+  EFI_TCP4_IO_TOKEN             *Tx4Token;\r
   EFI_TCP4_PROTOCOL             *Tcp4;\r
-  \r
-  Tcp4 = HttpInstance->Tcp4;\r
-  TxToken = &Wrap->TcpWrap.TxToken;\r
+  EFI_TCP6_IO_TOKEN             *Tx6Token;\r
+  EFI_TCP6_PROTOCOL             *Tcp6;\r
+  UINT8                         *TlsRecord;\r
+  UINT16                        PayloadSize;\r
+  NET_FRAGMENT                  TempFragment;\r
+  NET_FRAGMENT                  Fragment;\r
+  UINTN                         RecordCount;\r
+  UINTN                         RemainingLen;\r
+\r
+  Status                = EFI_SUCCESS;\r
+  TlsRecord             = NULL;\r
+  PayloadSize           = 0;\r
+  TempFragment.Len      = 0;\r
+  TempFragment.Bulk     = NULL;\r
+  Fragment.Len          = 0;\r
+  Fragment.Bulk         = NULL;\r
+  RecordCount           = 0;\r
+  RemainingLen          = 0;\r
 \r
-  TxToken->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
-  TxToken->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
-  TxToken->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
-  TxToken->CompletionToken.Status = EFI_NOT_READY;  \r
+  //\r
+  // Need to encrypt data.\r
+  //\r
+  if (HttpInstance->UseHttps) {\r
+    //\r
+    // Allocate enough buffer for each TLS plaintext records.\r
+    //\r
+    TlsRecord = AllocateZeroPool (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
+    if (TlsRecord == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      return Status;\r
+    }\r
 \r
-  Wrap->TcpWrap.IsTxDone = FALSE;\r
-  Status  = Tcp4->Transmit (Tcp4, TxToken);\r
-  if (EFI_ERROR (Status)) {\r
-    DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
-    return Status;\r
+    //\r
+    // Allocate enough buffer for all TLS ciphertext records.\r
+    //\r
+    RecordCount = TxStringLen / TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH + 1;\r
+    Fragment.Bulk = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));\r
+    if (Fragment.Bulk == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    //\r
+    // Encrypt each TLS plaintext records.\r
+    //\r
+    RemainingLen = TxStringLen;\r
+    while (RemainingLen != 0) {\r
+      PayloadSize = (UINT16) MIN (TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH, RemainingLen);\r
+\r
+      ((TLS_RECORD_HEADER *) TlsRecord)->ContentType = TlsContentTypeApplicationData;\r
+      ((TLS_RECORD_HEADER *) TlsRecord)->Version.Major = HttpInstance->TlsConfigData.Version.Major;\r
+      ((TLS_RECORD_HEADER *) TlsRecord)->Version.Minor = HttpInstance->TlsConfigData.Version.Minor;\r
+      ((TLS_RECORD_HEADER *) TlsRecord)->Length = PayloadSize;\r
+\r
+      CopyMem (TlsRecord + TLS_RECORD_HEADER_LENGTH, TxString + (TxStringLen - RemainingLen), PayloadSize);\r
+\r
+      Status = TlsProcessMessage (\r
+                 HttpInstance,\r
+                 TlsRecord,\r
+                 TLS_RECORD_HEADER_LENGTH + PayloadSize,\r
+                 EfiTlsEncrypt,\r
+                 &TempFragment\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_ERROR;\r
+      }\r
+\r
+      //\r
+      // Record the processed/encrypted Packet.\r
+      //\r
+      CopyMem (Fragment.Bulk + Fragment.Len, TempFragment.Bulk, TempFragment.Len);\r
+      Fragment.Len += TempFragment.Len;\r
+\r
+      FreePool (TempFragment.Bulk);\r
+      TempFragment.Len  = 0;\r
+      TempFragment.Bulk = NULL;\r
+\r
+      RemainingLen -= (UINTN) PayloadSize;\r
+      ZeroMem (TlsRecord, TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);\r
+    }\r
+\r
+    FreePool (TlsRecord);\r
+    TlsRecord = NULL;\r
   }\r
 \r
-  return Status;\r
-}\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    Tcp4 = HttpInstance->Tcp4;\r
+    Tx4Token = &Wrap->TcpWrap.Tx4Token;\r
+\r
+    if (HttpInstance->UseHttps) {\r
+      Tx4Token->Packet.TxData->DataLength = Fragment.Len;\r
+      Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
+      Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
+    } else {\r
+      Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
+      Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
+      Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
+    }\r
 \r
-/**\r
-  Translate the status code in HTTP message to EFI_HTTP_STATUS_CODE defined \r
-  in UEFI 2.5 specification.\r
+    Tx4Token->CompletionToken.Status = EFI_NOT_READY;\r
 \r
-  @param[in]  StatusCode         The status code value in HTTP message.\r
+    Wrap->TcpWrap.IsTxDone = FALSE;\r
+    Status  = Tcp4->Transmit (Tcp4, Tx4Token);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
+      goto ON_ERROR;\r
+    }\r
+\r
+  } else {\r
+    Tcp6 = HttpInstance->Tcp6;\r
+    Tx6Token = &Wrap->TcpWrap.Tx6Token;\r
+\r
+    if (HttpInstance->UseHttps) {\r
+      Tx6Token->Packet.TxData->DataLength = Fragment.Len;\r
+      Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = Fragment.Len;\r
+      Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) Fragment.Bulk;\r
+    } else {\r
+      Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;\r
+      Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32) TxStringLen;\r
+      Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *) TxString;\r
+    }\r
 \r
-  @return                        Value defined in EFI_HTTP_STATUS_CODE .\r
+    Tx6Token->CompletionToken.Status = EFI_NOT_READY;\r
 \r
-**/\r
-EFI_HTTP_STATUS_CODE\r
-HttpMappingToStatusCode (\r
-  IN UINTN                  StatusCode\r
-  )  \r
-{\r
-  switch (StatusCode) {\r
-  case 100:\r
-    return HTTP_STATUS_100_CONTINUE;\r
-  case 101:\r
-    return HTTP_STATUS_101_SWITCHING_PROTOCOLS;\r
-  case 200:\r
-    return HTTP_STATUS_200_OK;\r
-  case 201:\r
-    return HTTP_STATUS_201_CREATED;\r
-  case 202:\r
-    return HTTP_STATUS_202_ACCEPTED;\r
-  case 203:\r
-    return HTTP_STATUS_203_NON_AUTHORITATIVE_INFORMATION;\r
-  case 204:\r
-    return HTTP_STATUS_204_NO_CONTENT;\r
-  case 205:\r
-    return HTTP_STATUS_205_RESET_CONTENT;\r
-  case 206:\r
-    return HTTP_STATUS_206_PARTIAL_CONTENT;\r
-  case 300:\r
-    return HTTP_STATUS_300_MULTIPLE_CHIOCES;\r
-  case 301:\r
-    return HTTP_STATUS_301_MOVED_PERMANENTLY;\r
-  case 302:\r
-    return HTTP_STATUS_302_FOUND;\r
-  case 303:\r
-    return HTTP_STATUS_303_SEE_OTHER;\r
-  case 304:\r
-    return HTTP_STATUS_304_NOT_MODIFIED;\r
-  case 305:\r
-    return HTTP_STATUS_305_USE_PROXY;\r
-  case 307:\r
-    return HTTP_STATUS_307_TEMPORARY_REDIRECT;\r
-  case 400:\r
-    return HTTP_STATUS_400_BAD_REQUEST;\r
-  case 401:\r
-    return HTTP_STATUS_401_UNAUTHORIZED;\r
-  case 402:\r
-    return HTTP_STATUS_402_PAYMENT_REQUIRED;\r
-  case 403:\r
-    return HTTP_STATUS_403_FORBIDDEN;\r
-  case 404:\r
-    return HTTP_STATUS_404_NOT_FOUND;\r
-  case 405:\r
-    return HTTP_STATUS_405_METHOD_NOT_ALLOWED;\r
-  case 406:\r
-    return HTTP_STATUS_406_NOT_ACCEPTABLE;\r
-  case 407:\r
-    return HTTP_STATUS_407_PROXY_AUTHENTICATION_REQUIRED;\r
-  case 408:\r
-    return HTTP_STATUS_408_REQUEST_TIME_OUT;\r
-  case 409:\r
-    return HTTP_STATUS_409_CONFLICT;\r
-  case 410:\r
-    return HTTP_STATUS_410_GONE;\r
-  case 411:\r
-    return HTTP_STATUS_411_LENGTH_REQUIRED;\r
-  case 412:\r
-    return HTTP_STATUS_412_PRECONDITION_FAILED;\r
-  case 413:\r
-    return HTTP_STATUS_413_REQUEST_ENTITY_TOO_LARGE;\r
-  case 414:\r
-    return HTTP_STATUS_414_REQUEST_URI_TOO_LARGE;\r
-  case 415:\r
-    return HTTP_STATUS_415_UNSUPPORTED_MEDIA_TYPE;\r
-  case 416:\r
-    return HTTP_STATUS_416_REQUESTED_RANGE_NOT_SATISFIED;\r
-  case 417:\r
-    return HTTP_STATUS_417_EXPECTATION_FAILED;\r
-  case 500:\r
-    return HTTP_STATUS_500_INTERNAL_SERVER_ERROR;\r
-  case 501:\r
-    return HTTP_STATUS_501_NOT_IMPLEMENTED;\r
-  case 502:\r
-    return HTTP_STATUS_502_BAD_GATEWAY;\r
-  case 503:\r
-    return HTTP_STATUS_503_SERVICE_UNAVAILABLE;\r
-  case 504:\r
-    return HTTP_STATUS_504_GATEWAY_TIME_OUT;\r
-  case 505:\r
-    return HTTP_STATUS_505_HTTP_VERSION_NOT_SUPPORTED;\r
-\r
-  default:\r
-    return HTTP_STATUS_UNSUPPORTED_STATUS;\r
+    Wrap->TcpWrap.IsTxDone = FALSE;\r
+    Status = Tcp6->Transmit (Tcp6, Tx6Token);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));\r
+      goto ON_ERROR;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+\r
+ON_ERROR:\r
+\r
+  if (HttpInstance->UseHttps) {\r
+    if (TlsRecord != NULL) {\r
+      FreePool (TlsRecord);\r
+      TlsRecord = NULL;\r
+    }\r
+\r
+    if (Fragment.Bulk != NULL) {\r
+      FreePool (Fragment.Bulk);\r
+      Fragment.Bulk = NULL;\r
+    }\r
   }\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
   Check whether the user's token or event has already\r
-  been enqueue on HTTP TxToken or RxToken list.\r
+  been enqueue on HTTP Tx or Rx Token list.\r
 \r
   @param[in]  Map                The container of either user's transmit or receive\r
                                  token.\r
@@ -953,9 +1665,9 @@ HttpTokenExist (
 }\r
 \r
 /**\r
-  Check whether the HTTP message associated with TxToken is already sent out.\r
+  Check whether the HTTP message associated with Tx4Token or Tx6Token is already sent out.\r
 \r
-  @param[in]  Map                The container of TxToken.\r
+  @param[in]  Map                The container of Tx4Token or Tx6Token.\r
   @param[in]  Item               Current item to check against.\r
   @param[in]  Context            The Token to check againist.\r
 \r
@@ -978,14 +1690,14 @@ HttpTcpNotReady (
   if (!ValueInItem->TcpWrap.IsTxDone) {\r
     return EFI_NOT_READY;\r
   }\r
-  \r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Transmit the HTTP mssage by processing the associated HTTP token.\r
+  Transmit the HTTP or HTTPS mssage by processing the associated HTTP token.\r
 \r
-  @param[in]  Map                The container of TxToken.\r
+  @param[in]  Map                The container of Tx4Token or Tx6Token.\r
   @param[in]  Item               Current item to check against.\r
   @param[in]  Context            The Token to check againist.\r
 \r
@@ -1004,8 +1716,12 @@ HttpTcpTransmit (
 {\r
   HTTP_TOKEN_WRAP           *ValueInItem;\r
   EFI_STATUS                Status;\r
-  CHAR8                     *RequestStr;\r
+  CHAR8                     *RequestMsg;\r
   CHAR8                     *Url;\r
+  UINTN                     UrlSize;\r
+  UINTN                     RequestMsgSize;\r
+\r
+  RequestMsg = NULL;\r
 \r
   ValueInItem = (HTTP_TOKEN_WRAP *) Item->Value;\r
   if (ValueInItem->TcpWrap.IsTxDone) {\r
@@ -1015,43 +1731,48 @@ HttpTcpTransmit (
   //\r
   // Parse the URI of the remote host.\r
   //\r
-  Url = AllocatePool (StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1);\r
+  UrlSize = StrLen (ValueInItem->HttpToken->Message->Data.Request->Url) + 1;\r
+  Url = AllocatePool (UrlSize);\r
   if (Url == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  UnicodeStrToAsciiStr (ValueInItem->HttpToken->Message->Data.Request->Url, Url);\r
+  UnicodeStrToAsciiStrS (ValueInItem->HttpToken->Message->Data.Request->Url, Url, UrlSize);\r
 \r
   //\r
   // Create request message.\r
   //\r
-  RequestStr = HttpGenRequestString (\r
-                 ValueInItem->HttpInstance,\r
+  Status = HttpGenRequestMessage (\r
                  ValueInItem->HttpToken->Message,\r
-                 Url\r
+                 Url,\r
+                 &RequestMsg,\r
+                 &RequestMsgSize\r
                  );\r
   FreePool (Url);\r
-  if (RequestStr == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+\r
+  if (EFI_ERROR (Status) || NULL == RequestMsg){\r
+    return Status;\r
   }\r
 \r
+  ASSERT (RequestMsg != NULL);\r
+\r
   //\r
   // Transmit the request message.\r
   //\r
-  Status = HttpTransmitTcp4 (\r
+  Status = HttpTransmitTcp (\r
              ValueInItem->HttpInstance,\r
              ValueInItem,\r
-             (UINT8*) RequestStr,\r
-             AsciiStrLen (RequestStr)\r
+             (UINT8*) RequestMsg,\r
+             RequestMsgSize\r
              );\r
-  FreePool (RequestStr);\r
+  FreePool (RequestMsg);\r
   return Status;\r
 }\r
 \r
 /**\r
   Receive the HTTP response by processing the associated HTTP token.\r
 \r
-  @param[in]  Map                The container of RxToken.\r
+  @param[in]  Map                The container of Rx4Token or Rx6Token.\r
   @param[in]  Item               Current item to check against.\r
   @param[in]  Context            The Token to check againist.\r
 \r
@@ -1075,153 +1796,401 @@ HttpTcpReceive (
 }\r
 \r
 /**\r
-  Generate HTTP request string.\r
+  Receive the HTTP header by processing the associated HTTP token.\r
 \r
-  @param[in]  HttpInstance       Pointer to HTTP_PROTOCOL structure.\r
-  @param[in]  Message            Pointer to storage containing HTTP message data.\r
-  @param[in]  Url                The URL of a remote host.\r
+  @param[in]       HttpInstance     The HTTP instance private data.\r
+  @param[in, out]  SizeofHeaders    The HTTP header length.\r
+  @param[in, out]  BufferSize       The size of buffer to cacahe the header message.\r
+  @param[in]       Timeout          The time to wait for receiving the header packet.\r
 \r
-  @return     Pointer to the created HTTP request string.\r
-  @return     NULL if any error occured.\r
+  @retval EFI_SUCCESS               The HTTP header is received.\r
+  @retval Others                    Other errors as indicated.\r
 \r
 **/\r
-CHAR8 *\r
-HttpGenRequestString (\r
-  IN  HTTP_PROTOCOL        *HttpInstance,\r
-  IN  EFI_HTTP_MESSAGE     *Message,\r
-  IN  CHAR8                *Url\r
+EFI_STATUS\r
+HttpTcpReceiveHeader (\r
+  IN  HTTP_PROTOCOL         *HttpInstance,\r
+  IN  OUT UINTN             *SizeofHeaders,\r
+  IN  OUT UINTN             *BufferSize,\r
+  IN  EFI_EVENT             Timeout\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINTN                       StrLength;\r
-  UINT8                       *Request;\r
-  UINT8                       *RequestPtr;\r
-  UINTN                       HttpHdrSize;\r
-  UINTN                       MsgSize;\r
-  BOOLEAN                     Success;\r
-  VOID                        *HttpHdr;\r
-  EFI_HTTP_HEADER             **AppendList; \r
-  UINTN                       Index;\r
-  \r
-  ASSERT (HttpInstance != NULL);\r
-  ASSERT (Message != NULL);\r
+  EFI_STATUS                    Status;\r
+  EFI_TCP4_IO_TOKEN             *Rx4Token;\r
+  EFI_TCP4_PROTOCOL             *Tcp4;\r
+  EFI_TCP6_IO_TOKEN             *Rx6Token;\r
+  EFI_TCP6_PROTOCOL             *Tcp6;\r
+  CHAR8                         **EndofHeader;\r
+  CHAR8                         **HttpHeaders;\r
+  CHAR8                         *Buffer;\r
+  NET_FRAGMENT                  Fragment;\r
 \r
-  DEBUG ((EFI_D_ERROR, "HttpMethod - %x\n", Message->Data.Request->Method));\r
+  ASSERT (HttpInstance != NULL);\r
 \r
-  Request = NULL;\r
-  Success = FALSE;\r
-  HttpHdr = NULL;\r
-  AppendList = NULL;\r
+  EndofHeader = HttpInstance->EndofHeader;\r
+  HttpHeaders = HttpInstance->HttpHeaders;\r
+  Tcp4 = HttpInstance->Tcp4;\r
+  Tcp6 = HttpInstance->Tcp6;\r
+  Buffer      = NULL;\r
+  Rx4Token    = NULL;\r
+  Rx6Token    = NULL;\r
+  Fragment.Len  = 0;\r
+  Fragment.Bulk = NULL;\r
+\r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    ASSERT (Tcp6 != NULL);\r
+  } else {\r
+    ASSERT (Tcp4 != NULL);\r
+  }\r
 \r
-  //\r
-  // Build AppendList\r
-  //\r
-  AppendList = AllocateZeroPool (sizeof (EFI_HTTP_HEADER *) * (Message->HeaderCount));\r
-  if (AppendList == NULL) {\r
-    return NULL;\r
+  if (!HttpInstance->UseHttps) {\r
+    Status = HttpCreateTcpRxEventForHeader (HttpInstance);\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
-  for(Index = 0; Index < Message->HeaderCount; Index++){\r
-    AppendList[Index] = &Message->Headers[Index];\r
+  if (!HttpInstance->LocalAddressIsIPv6) {\r
+    if (!HttpInstance->UseHttps) {\r
+      Rx4Token = &HttpInstance->Rx4Token;\r
+      Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
+      if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
+    //\r
+    while (*EndofHeader == NULL) {\r
+      if (!HttpInstance->UseHttps) {\r
+        HttpInstance->IsRxDone = FALSE;\r
+        Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
+        Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
+        Status = Tcp4->Receive (Tcp4, Rx4Token);\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
+          return Status;\r
+        }\r
+\r
+        while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
+          Tcp4->Poll (Tcp4);\r
+        }\r
+\r
+        if (!HttpInstance->IsRxDone) {\r
+          //\r
+          // Cancle the Token before close its Event.\r
+          //\r
+          Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);\r
+          gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
+          Rx4Token->CompletionToken.Status = EFI_TIMEOUT;\r
+        }\r
+\r
+        Status = Rx4Token->CompletionToken.Status;\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        Fragment.Len  = Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
+        Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
+      } else {\r
+        if (Fragment.Bulk != NULL) {\r
+          FreePool (Fragment.Bulk);\r
+          Fragment.Bulk = NULL;\r
+        }\r
+\r
+        Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
+          return Status;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Append the response string along with a Null-terminator.\r
+      //\r
+      *BufferSize = *SizeofHeaders + Fragment.Len;\r
+      Buffer      = AllocatePool (*BufferSize + 1);\r
+      if (Buffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        return Status;\r
+      }\r
+\r
+      if (*HttpHeaders != NULL) {\r
+        CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
+        FreePool (*HttpHeaders);\r
+      }\r
+\r
+      CopyMem (\r
+        Buffer + *SizeofHeaders,\r
+        Fragment.Bulk,\r
+        Fragment.Len\r
+        );\r
+      *(Buffer + *BufferSize) = '\0';\r
+      *HttpHeaders   = Buffer;\r
+      *SizeofHeaders = *BufferSize;\r
+\r
+      //\r
+      // Check whether we received end of HTTP headers.\r
+      //\r
+      *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
+    };\r
+\r
+    //\r
+    // Free the buffer.\r
+    //\r
+    if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL && Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+      FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+      Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
+      Fragment.Bulk = NULL;\r
+    }\r
+\r
+    if (Fragment.Bulk != NULL) {\r
+      FreePool (Fragment.Bulk);\r
+      Fragment.Bulk = NULL;\r
+    }\r
+  } else {\r
+    if (!HttpInstance->UseHttps) {\r
+      Rx6Token = &HttpInstance->Rx6Token;\r
+      Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = AllocateZeroPool (DEF_BUF_LEN);\r
+      if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        return Status;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not NULL.\r
+    //\r
+    while (*EndofHeader == NULL) {\r
+      if (!HttpInstance->UseHttps) {\r
+        HttpInstance->IsRxDone = FALSE;\r
+        Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;\r
+        Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength = DEF_BUF_LEN;\r
+        Status = Tcp6->Receive (Tcp6, Rx6Token);\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
+          return Status;\r
+        }\r
+\r
+        while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {\r
+          Tcp6->Poll (Tcp6);\r
+        }\r
+\r
+        if (!HttpInstance->IsRxDone) {\r
+          //\r
+          // Cancle the Token before close its Event.\r
+          //\r
+          Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);\r
+          gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
+          Rx6Token->CompletionToken.Status = EFI_TIMEOUT;\r
+        }\r
+\r
+        Status = Rx6Token->CompletionToken.Status;\r
+        if (EFI_ERROR (Status)) {\r
+          return Status;\r
+        }\r
+\r
+        Fragment.Len  = Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength;\r
+        Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer;\r
+      } else {\r
+        if (Fragment.Bulk != NULL) {\r
+          FreePool (Fragment.Bulk);\r
+          Fragment.Bulk = NULL;\r
+        }\r
+\r
+        Status = HttpsReceive (HttpInstance, &Fragment, Timeout);\r
+        if (EFI_ERROR (Status)) {\r
+          DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
+          return Status;\r
+        }\r
+      }\r
+\r
+      //\r
+      // Append the response string along with a Null-terminator.\r
+      //\r
+      *BufferSize = *SizeofHeaders + Fragment.Len;\r
+      Buffer      = AllocatePool (*BufferSize + 1);\r
+      if (Buffer == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        return Status;\r
+      }\r
+\r
+      if (*HttpHeaders != NULL) {\r
+        CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);\r
+        FreePool (*HttpHeaders);\r
+      }\r
+\r
+      CopyMem (\r
+        Buffer + *SizeofHeaders,\r
+        Fragment.Bulk,\r
+        Fragment.Len\r
+        );\r
+      *(Buffer + *BufferSize) = '\0';\r
+      *HttpHeaders   = Buffer;\r
+      *SizeofHeaders = *BufferSize;\r
+\r
+      //\r
+      // Check whether we received end of HTTP headers.\r
+      //\r
+      *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);\r
+    };\r
+\r
+    //\r
+    // Free the buffer.\r
+    //\r
+    if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL && Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+      FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+      Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
+      Fragment.Bulk = NULL;\r
+    }\r
+\r
+    if (Fragment.Bulk != NULL) {\r
+      FreePool (Fragment.Bulk);\r
+      Fragment.Bulk = NULL;\r
+    }\r
   }\r
 \r
   //\r
-  // Check whether the EFI_HTTP_UTILITIES_PROTOCOL is available.\r
+  // Skip the CRLF after the HTTP headers.\r
   //\r
-  if (mHttpUtilities == NULL) {\r
-    return NULL;\r
+  *EndofHeader = *EndofHeader + AsciiStrLen (HTTP_END_OF_HDR_STR);\r
+\r
+  *SizeofHeaders = *EndofHeader - *HttpHeaders;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Receive the HTTP body by processing the associated HTTP token.\r
+\r
+  @param[in]  Wrap               The HTTP token's wrap data.\r
+  @param[in]  HttpMsg            The HTTP message data.\r
+\r
+  @retval EFI_SUCCESS            The HTTP body is received.\r
+  @retval Others                 Other error as indicated.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpTcpReceiveBody (\r
+  IN  HTTP_TOKEN_WRAP       *Wrap,\r
+  IN  EFI_HTTP_MESSAGE      *HttpMsg\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  HTTP_PROTOCOL             *HttpInstance;\r
+  EFI_TCP6_PROTOCOL         *Tcp6;\r
+  EFI_TCP6_IO_TOKEN         *Rx6Token;\r
+  EFI_TCP4_PROTOCOL         *Tcp4;\r
+  EFI_TCP4_IO_TOKEN         *Rx4Token;\r
+\r
+  HttpInstance   = Wrap->HttpInstance;\r
+  Tcp4 = HttpInstance->Tcp4;\r
+  Tcp6 = HttpInstance->Tcp6;\r
+  Rx4Token       = NULL;\r
+  Rx6Token       = NULL;\r
+\r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    ASSERT (Tcp6 != NULL);\r
+  } else {\r
+    ASSERT (Tcp4 != NULL);\r
   }\r
 \r
-  //\r
-  // Build raw unformatted HTTP headers.\r
-  //\r
-  Status = mHttpUtilities->Build (\r
-                             mHttpUtilities,\r
-                             0,\r
-                             NULL,\r
-                             0,\r
-                             NULL,\r
-                             Message->HeaderCount,\r
-                             AppendList,\r
-                             &HttpHdrSize,\r
-                             &HttpHdr\r
-                             );\r
-  FreePool (AppendList);\r
-  if (EFI_ERROR (Status) || HttpHdr == NULL) {\r
-    return NULL;\r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
+    Rx6Token ->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
+    Rx6Token ->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
+    Rx6Token ->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
+    Rx6Token->CompletionToken.Status = EFI_NOT_READY;\r
+\r
+    Status = Tcp6->Receive (Tcp6, Rx6Token);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));\r
+      return Status;\r
+    }\r
+  } else {\r
+    Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
+    Rx4Token->Packet.RxData->DataLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
+    Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength = (UINT32) MIN (MAX_UINT32, HttpMsg->BodyLength);\r
+    Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = (VOID *) HttpMsg->Body;\r
+\r
+    Rx4Token->CompletionToken.Status = EFI_NOT_READY;\r
+    Status = Tcp4->Receive (Tcp4, Rx4Token);\r
+    if (EFI_ERROR (Status)) {\r
+      DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));\r
+      return Status;\r
+    }\r
   }\r
 \r
-  //\r
-  // Calculate HTTP message length.\r
-  //\r
-  MsgSize = Message->BodyLength + HTTP_MAXIMUM_METHOD_LEN + AsciiStrLen (Url) + \r
-            AsciiStrLen (HTTP_VERSION_CRLF_STR) + HttpHdrSize;\r
-  Request = AllocateZeroPool (MsgSize);\r
-  if (Request == NULL) {\r
-    goto Exit;\r
-  }  \r
-\r
-  RequestPtr = Request;\r
-  //\r
-  // Construct header request\r
-  //\r
-  switch (Message->Data.Request->Method) {\r
-  case HttpMethodGet:\r
-    StrLength = sizeof (HTTP_GET_STR) - 1;\r
-    CopyMem (RequestPtr, HTTP_GET_STR, StrLength);\r
-    RequestPtr += StrLength;\r
-    break;\r
-  case HttpMethodHead:\r
-    StrLength = sizeof (HTTP_HEAD_STR) - 1;\r
-    CopyMem (RequestPtr, HTTP_HEAD_STR, StrLength);\r
-    RequestPtr += StrLength;\r
-    break;\r
-  default:\r
-    ASSERT (FALSE);\r
-    goto Exit;\r
-  }\r
-\r
-  StrLength = AsciiStrLen (Url);\r
-  CopyMem (RequestPtr, Url, StrLength);\r
-  RequestPtr += StrLength;\r
-\r
-  StrLength = sizeof (HTTP_VERSION_CRLF_STR) - 1;\r
-  CopyMem (RequestPtr, HTTP_VERSION_CRLF_STR, StrLength);\r
-  RequestPtr += StrLength;\r
+  return EFI_SUCCESS;\r
 \r
-  //\r
-  // Construct header\r
-  //\r
-  CopyMem (RequestPtr, HttpHdr, HttpHdrSize);\r
-  RequestPtr += HttpHdrSize;\r
+}\r
 \r
-  //\r
-  // Construct body\r
-  //\r
-  if (Message->Body != NULL) {\r
-    CopyMem (RequestPtr, Message->Body, Message->BodyLength);\r
-    RequestPtr += Message->BodyLength;\r
-  }\r
+/**\r
+  Clean up Tcp Tokens while the Tcp transmission error occurs.\r
 \r
-  //\r
-  // Done\r
-  //\r
-  *RequestPtr = 0;\r
-  Success     = TRUE;\r
-  \r
-Exit:\r
+  @param[in]  Wrap               Pointer to HTTP token's wrap data.\r
 \r
-  if (!Success) {\r
-    if (Request != NULL) {\r
-      FreePool (Request);\r
+**/\r
+VOID\r
+HttpTcpTokenCleanup (\r
+  IN  HTTP_TOKEN_WRAP      *Wrap\r
+  )\r
+{\r
+  HTTP_PROTOCOL            *HttpInstance;\r
+  EFI_TCP4_IO_TOKEN        *Rx4Token;\r
+  EFI_TCP6_IO_TOKEN        *Rx6Token;\r
+\r
+  ASSERT (Wrap != NULL);\r
+  HttpInstance   = Wrap->HttpInstance;\r
+  Rx4Token       = NULL;\r
+  Rx6Token       = NULL;\r
+\r
+  if (HttpInstance->LocalAddressIsIPv6) {\r
+    Rx6Token = &Wrap->TcpWrap.Rx6Token;\r
+\r
+    if (Rx6Token->CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
+      Rx6Token->CompletionToken.Event = NULL;\r
     }\r
 \r
-    Request = NULL;\r
-  }\r
+    FreePool (Wrap);\r
+\r
+    Rx6Token = &HttpInstance->Rx6Token;\r
+\r
+    if (Rx6Token->CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Rx6Token->CompletionToken.Event);\r
+      Rx6Token->CompletionToken.Event = NULL;\r
+    }\r
+\r
+    if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+      FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+      Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
+    }\r
+\r
+  } else {\r
+    Rx4Token = &Wrap->TcpWrap.Rx4Token;\r
+\r
+    if (Rx4Token->CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
+      Rx4Token->CompletionToken.Event = NULL;\r
+    }\r
 \r
-  if (HttpHdr != NULL) {\r
-    FreePool (HttpHdr);\r
+    FreePool (Wrap);\r
+\r
+    Rx4Token = &HttpInstance->Rx4Token;\r
+\r
+    if (Rx4Token->CompletionToken.Event != NULL) {\r
+      gBS->CloseEvent (Rx4Token->CompletionToken.Event);\r
+      Rx4Token->CompletionToken.Event = NULL;\r
+    }\r
+\r
+\r
+    if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {\r
+      FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);\r
+      Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;\r
+    }\r
   }\r
 \r
-  return (CHAR8*) Request;\r
 }\r