v2:
* Fix the ASSERT issue.

Base on the request of https://bugzilla.tianocore.org/show_bug.cgi?id=710,
we provide this patch to IPv6 condition check by leveraging AIP Protocol.

Cc: Karunakar P <karunak...@amiindia.co.in>
Cc: Ye Ting <ting...@intel.com>
Cc: Fu Siyuan <siyuan...@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Karunakar P <karunak...@amiindia.co.in>
Signed-off-by: Wu Jiaxin <jiaxin...@intel.com>
---
 NetworkPkg/HttpBootDxe/HttpBootDxe.c   | 161 +++++++++++++++++++++++++++++++--
 NetworkPkg/HttpBootDxe/HttpBootDxe.h   |   2 +
 NetworkPkg/HttpBootDxe/HttpBootDxe.inf |   4 +-
 3 files changed, 157 insertions(+), 10 deletions(-)

diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.c 
b/NetworkPkg/HttpBootDxe/HttpBootDxe.c
index 642e0fe..b1f9042 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootDxe.c
+++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.c
@@ -1,9 +1,9 @@
 /** @file
   Driver Binding functions implementation for UEFI HTTP boot.
 
-Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
 This program and the accompanying materials are licensed and made available 
under 
 the terms and conditions of the BSD License that accompanies this 
distribution.  
 The full text of the license may be found at
 http://opensource.org/licenses/bsd-license.php.                                
          
     
@@ -33,10 +33,104 @@ EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp6DxeDriverBinding = 
{
   HTTP_BOOT_DXE_VERSION,
   NULL,
   NULL
 };
 
+
+
+/**
+  Check whether UNDI protocol supports IPv6.
+
+  @param[in]   Private           Pointer to HTTP_BOOT_PRIVATE_DATA.
+  @param[out]  Ipv6Support       TRUE if UNDI supports IPv6.
+
+  @retval EFI_SUCCESS            Get the result whether UNDI supports IPv6 by 
NII or AIP protocol successfully.
+  @retval EFI_NOT_FOUND          Don't know whether UNDI supports IPv6 since 
NII or AIP is not available.
+
+**/
+EFI_STATUS
+HttpBootCheckIpv6Support (
+  IN  HTTP_BOOT_PRIVATE_DATA       *Private,
+  OUT BOOLEAN                      *Ipv6Support
+  )
+{
+  EFI_HANDLE                       Handle;
+  EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
+  EFI_STATUS                       Status;
+  EFI_GUID                         *InfoTypesBuffer;
+  UINTN                            InfoTypeBufferCount;
+  UINTN                            TypeIndex;
+  BOOLEAN                          Supported;
+  VOID                             *InfoBlock;
+  UINTN                            InfoBlockSize;
+
+  ASSERT (Private != NULL && Ipv6Support != NULL);
+
+  //
+  // Check whether the UNDI supports IPv6 by NII protocol.
+  //
+  if (Private->Nii != NULL) {
+    *Ipv6Support = Private->Nii->Ipv6Supported;
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Get the NIC handle by SNP protocol.
+  //  
+  Handle = NetLibGetSnpHandle (Private->Controller, NULL);
+  if (Handle == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  Aip    = NULL;
+  Status = gBS->HandleProtocol (
+                  Handle,
+                  &gEfiAdapterInformationProtocolGuid,
+                  (VOID *) &Aip
+                  );
+  if (EFI_ERROR (Status) || Aip == NULL) {
+    return EFI_NOT_FOUND;
+  }
+
+  InfoTypesBuffer     = NULL;
+  InfoTypeBufferCount = 0;
+  Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, 
&InfoTypeBufferCount);
+  if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {
+    FreePool (InfoTypesBuffer);
+    return EFI_NOT_FOUND;
+  }
+
+  Supported = FALSE;
+  for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
+    if (CompareGuid (&InfoTypesBuffer[TypeIndex], 
&gEfiAdapterInfoUndiIpv6SupportGuid)) {
+      Supported = TRUE;
+      break;
+    }
+  }
+
+  FreePool (InfoTypesBuffer);
+  if (!Supported) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // We now have adapter information block.
+  //
+  InfoBlock     = NULL;
+  InfoBlockSize = 0;
+  Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, 
&InfoBlock, &InfoBlockSize);
+  if (EFI_ERROR (Status) || InfoBlock == NULL) {
+    FreePool (InfoBlock);
+    return EFI_NOT_FOUND;
+  }  
+
+  *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) 
InfoBlock)->Ipv6Support;
+  FreePool (InfoBlock);
+  
+  return EFI_SUCCESS;
+}
+
 /**
   Destroy the HTTP child based on IPv4 stack.
 
   @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
   @param[in]  Private           Pointer to HTTP_BOOT_PRIVATE_DATA.
@@ -65,11 +159,11 @@ HttpBootDestroyIp4Children (
       &gEfiDhcp4ServiceBindingProtocolGuid,
       Private->Dhcp4Child
       );
   }
 
-  if (Private->HttpCreated) {
+  if (Private->Ip6Nic == NULL && Private->HttpCreated) {
     HttpIoDestroyIo (&Private->HttpIo);
     Private->HttpCreated = FALSE;
   }
 
   if (Private->Ip4Nic != NULL) {
@@ -141,11 +235,11 @@ HttpBootDestroyIp6Children (
       &gEfiDhcp6ServiceBindingProtocolGuid,
       Private->Dhcp6Child
       );
   }
 
-  if (Private->HttpCreated) {
+  if (Private->Ip4Nic == NULL && Private->HttpCreated) {
     HttpIoDestroyIo(&Private->HttpIo);
     Private->HttpCreated = FALSE;
   }
   
   if (Private->Ip6Nic != NULL) {
@@ -308,10 +402,13 @@ HttpBootIp4DxeDriverBindingStart (
   EFI_STATUS                 Status;
   HTTP_BOOT_PRIVATE_DATA     *Private;
   EFI_DEV_PATH               *Node;
   EFI_DEVICE_PATH_PROTOCOL   *DevicePath;
   UINT32                     *Id;
+  BOOLEAN                    FirstStart;
+
+  FirstStart = FALSE;
 
   Status = gBS->OpenProtocol (
                   ControllerHandle,
                   &gEfiCallerIdGuid,
                   (VOID **) &Id,
@@ -321,10 +418,12 @@ HttpBootIp4DxeDriverBindingStart (
                   );
 
   if (!EFI_ERROR (Status)) {
     Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);
   } else {
+    FirstStart = TRUE;
+  
     //
     // Initialize the private data structure.
     //
     Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));
     if (Private == NULL) {
@@ -394,11 +493,12 @@ HttpBootIp4DxeDriverBindingStart (
     return EFI_SUCCESS;
   }
   
   Private->Ip4Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));
   if (Private->Ip4Nic == NULL) {
-    return EFI_OUT_OF_RESOURCES;
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
   }
   Private->Ip4Nic->Private     = Private;
   Private->Ip4Nic->ImageHandle = This->DriverBindingHandle;
   Private->Ip4Nic->Signature   = HTTP_BOOT_VIRTUAL_NIC_SIGNATURE;
   
@@ -511,17 +611,26 @@ HttpBootIp4DxeDriverBindingStart (
   if (EFI_ERROR (Status)) {
     goto ON_ERROR;
   }
   
   return EFI_SUCCESS;
-
     
 ON_ERROR:
-
+  if (FirstStart) {
+    gBS->UninstallProtocolInterface (
+           ControllerHandle,
+           &gEfiCallerIdGuid,
+           &Private->Id
+           );
+  }
+  
   HttpBootDestroyIp4Children (This, Private);
   HttpBootConfigFormUnload (Private);
-  FreePool (Private);
+
+  if (FirstStart && Private != NULL) {
+    FreePool (Private);
+  }
 
   return Status;
 }
 
 
@@ -780,10 +889,14 @@ HttpBootIp6DxeDriverBindingStart (
   EFI_STATUS                 Status;
   HTTP_BOOT_PRIVATE_DATA     *Private;
   EFI_DEV_PATH               *Node;
   EFI_DEVICE_PATH_PROTOCOL   *DevicePath;
   UINT32                     *Id;
+  BOOLEAN                    Ipv6Available;
+  BOOLEAN                    FirstStart;
+
+  FirstStart = FALSE;
   
   Status = gBS->OpenProtocol (
                   ControllerHandle,
                   &gEfiCallerIdGuid,
                   (VOID **) &Id,
@@ -793,10 +906,12 @@ HttpBootIp6DxeDriverBindingStart (
                   );
   
   if (!EFI_ERROR (Status)) {
     Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);
   } else {
+    FirstStart = TRUE;
+    
     //
     // Initialize the private data structure.
     //
     Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));
     if (Private == NULL) {
@@ -856,21 +971,39 @@ HttpBootIp6DxeDriverBindingStart (
     if (EFI_ERROR (Status)) {
       goto ON_ERROR;
     }
       
   }
+
+  //
+  // Set IPv6 available flag.
+  // 
+  Status = HttpBootCheckIpv6Support (Private, &Ipv6Available);
+  if (EFI_ERROR (Status)) {
+    //
+    // Fail to get the data whether UNDI supports IPv6. 
+    // Set default value to TRUE.
+    //
+    Ipv6Available = TRUE;
+  }
+
+  if (!Ipv6Available) {
+    Status = EFI_UNSUPPORTED;
+    goto ON_ERROR;
+  }
   
   if (Private->Ip6Nic != NULL) {
     //
     // Already created before
     //
     return EFI_SUCCESS;
   }
   
   Private->Ip6Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));
   if (Private->Ip6Nic == NULL) {
-    return EFI_OUT_OF_RESOURCES;
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_ERROR;
   }
   Private->Ip6Nic->Private     = Private;
   Private->Ip6Nic->ImageHandle = This->DriverBindingHandle;
   Private->Ip6Nic->Signature   = HTTP_BOOT_VIRTUAL_NIC_SIGNATURE;
   
@@ -1009,14 +1142,24 @@ HttpBootIp6DxeDriverBindingStart (
   }
 
   return EFI_SUCCESS;
    
 ON_ERROR:
+  if (FirstStart) {
+    gBS->UninstallProtocolInterface (
+           ControllerHandle,
+           &gEfiCallerIdGuid,
+           &Private->Id
+           );
+  }
 
   HttpBootDestroyIp6Children(This, Private);
   HttpBootConfigFormUnload (Private);
-  FreePool (Private);
+
+  if (FirstStart && Private != NULL) {
+    FreePool (Private);
+  }
 
   return Status;
 }
 
 /**
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.h 
b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
index 2c07cf7..166bc45 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootDxe.h
+++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.h
@@ -56,10 +56,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER 
EXPRESS OR IMPLIED.
 #include <Protocol/Dns6.h>
 #include <Protocol/Http.h>
 #include <Protocol/Ip4Config2.h>
 #include <Protocol/Ip6Config.h>
 #include <Protocol/RamDisk.h>
+#include <Protocol/AdapterInformation.h>
+
 //
 // Produced Protocols
 //
 #include <Protocol/LoadFile.h>
 #include <Protocol/HttpBootCallback.h>
diff --git a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf 
b/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
index 4d6c5e5..6d2a772 100644
--- a/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
+++ b/NetworkPkg/HttpBootDxe/HttpBootDxe.inf
@@ -84,19 +84,21 @@
   gEfiIp6ConfigProtocolGuid                       ## TO_START
   gEfiNetworkInterfaceIdentifierProtocolGuid_31   ## SOMETIMES_CONSUMES
   gEfiRamDiskProtocolGuid                         ## SOMETIMES_CONSUMES
   gEfiHiiConfigAccessProtocolGuid                 ## BY_START
   gEfiHttpBootCallbackProtocolGuid                ## SOMETIMES_PRODUCES
-  
+  gEfiAdapterInformationProtocolGuid              ## SOMETIMES_CONSUMES
+
 [Guids]
   ## SOMETIMES_CONSUMES ## GUID # HiiIsConfigHdrMatch   
mHttpBootConfigStorageName
   ## SOMETIMES_PRODUCES ## GUID # HiiConstructConfigHdr 
mHttpBootConfigStorageName
   ## SOMETIMES_PRODUCES ## GUID # HiiGetBrowserData     
mHttpBootConfigStorageName
   ## SOMETIMES_CONSUMES ## HII
   gHttpBootConfigGuid
   gEfiVirtualCdGuid            ## SOMETIMES_CONSUMES ## GUID
   gEfiVirtualDiskGuid          ## SOMETIMES_CONSUMES ## GUID
+  gEfiAdapterInfoUndiIpv6SupportGuid             ## SOMETIMES_CONSUMES ## GUID
 
 [Pcd]
   gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections       ## CONSUMES  
 
 [UserExtensions.TianoCore."ExtraFiles"]
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to