]> git.proxmox.com Git - mirror_edk2.git/commitdiff
NetworkPkg/HttpBootDxe: Add IPv6 support condition check.
authorJiaxin Wu <jiaxin.wu@intel.com>
Tue, 17 Oct 2017 01:47:00 +0000 (09:47 +0800)
committerJiaxin Wu <jiaxin.wu@intel.com>
Thu, 26 Oct 2017 08:21:03 +0000 (16:21 +0800)
v2:
* Fix the potential 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 <karunakarp@amiindia.co.in>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Karunakar P <karunakarp@amiindia.co.in>
Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
Reviewed-by: Karunakar p <karunakarp@amiindia.co.in>
Reviewed-by: Wu Jiaxin <jiaxin.wu@intel.com>
NetworkPkg/HttpBootDxe/HttpBootDxe.c
NetworkPkg/HttpBootDxe/HttpBootDxe.h
NetworkPkg/HttpBootDxe/HttpBootDxe.inf

index 642e0fe31ee5de9028ed749ab565786c7495ddf1..b1f9042ea349b9b8c74cc35049e320545cdd780c 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Driver Binding functions implementation for UEFI HTTP boot.\r
 \r
-Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials are licensed and made available under \r
 the terms and conditions of the BSD License that accompanies this distribution.  \r
 The full text of the license may be found at\r
@@ -35,6 +35,100 @@ EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp6DxeDriverBinding = {
   NULL\r
 };\r
 \r
+\r
+\r
+/**\r
+  Check whether UNDI protocol supports IPv6.\r
+\r
+  @param[in]   Private           Pointer to HTTP_BOOT_PRIVATE_DATA.\r
+  @param[out]  Ipv6Support       TRUE if UNDI supports IPv6.\r
+\r
+  @retval EFI_SUCCESS            Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.\r
+  @retval EFI_NOT_FOUND          Don't know whether UNDI supports IPv6 since NII or AIP is not available.\r
+\r
+**/\r
+EFI_STATUS\r
+HttpBootCheckIpv6Support (\r
+  IN  HTTP_BOOT_PRIVATE_DATA       *Private,\r
+  OUT BOOLEAN                      *Ipv6Support\r
+  )\r
+{\r
+  EFI_HANDLE                       Handle;\r
+  EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;\r
+  EFI_STATUS                       Status;\r
+  EFI_GUID                         *InfoTypesBuffer;\r
+  UINTN                            InfoTypeBufferCount;\r
+  UINTN                            TypeIndex;\r
+  BOOLEAN                          Supported;\r
+  VOID                             *InfoBlock;\r
+  UINTN                            InfoBlockSize;\r
+\r
+  ASSERT (Private != NULL && Ipv6Support != NULL);\r
+\r
+  //\r
+  // Check whether the UNDI supports IPv6 by NII protocol.\r
+  //\r
+  if (Private->Nii != NULL) {\r
+    *Ipv6Support = Private->Nii->Ipv6Supported;\r
+    return EFI_SUCCESS;\r
+  }\r
+\r
+  //\r
+  // Get the NIC handle by SNP protocol.\r
+  //  \r
+  Handle = NetLibGetSnpHandle (Private->Controller, NULL);\r
+  if (Handle == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Aip    = NULL;\r
+  Status = gBS->HandleProtocol (\r
+                  Handle,\r
+                  &gEfiAdapterInformationProtocolGuid,\r
+                  (VOID *) &Aip\r
+                  );\r
+  if (EFI_ERROR (Status) || Aip == NULL) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  InfoTypesBuffer     = NULL;\r
+  InfoTypeBufferCount = 0;\r
+  Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);\r
+  if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {\r
+    FreePool (InfoTypesBuffer);\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  Supported = FALSE;\r
+  for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {\r
+    if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {\r
+      Supported = TRUE;\r
+      break;\r
+    }\r
+  }\r
+\r
+  FreePool (InfoTypesBuffer);\r
+  if (!Supported) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  //\r
+  // We now have adapter information block.\r
+  //\r
+  InfoBlock     = NULL;\r
+  InfoBlockSize = 0;\r
+  Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);\r
+  if (EFI_ERROR (Status) || InfoBlock == NULL) {\r
+    FreePool (InfoBlock);\r
+    return EFI_NOT_FOUND;\r
+  }  \r
+\r
+  *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support;\r
+  FreePool (InfoBlock);\r
+  \r
+  return EFI_SUCCESS;\r
+}\r
+\r
 /**\r
   Destroy the HTTP child based on IPv4 stack.\r
 \r
@@ -67,7 +161,7 @@ HttpBootDestroyIp4Children (
       );\r
   }\r
 \r
-  if (Private->HttpCreated) {\r
+  if (Private->Ip6Nic == NULL && Private->HttpCreated) {\r
     HttpIoDestroyIo (&Private->HttpIo);\r
     Private->HttpCreated = FALSE;\r
   }\r
@@ -143,7 +237,7 @@ HttpBootDestroyIp6Children (
       );\r
   }\r
 \r
-  if (Private->HttpCreated) {\r
+  if (Private->Ip4Nic == NULL && Private->HttpCreated) {\r
     HttpIoDestroyIo(&Private->HttpIo);\r
     Private->HttpCreated = FALSE;\r
   }\r
@@ -310,6 +404,9 @@ HttpBootIp4DxeDriverBindingStart (
   EFI_DEV_PATH               *Node;\r
   EFI_DEVICE_PATH_PROTOCOL   *DevicePath;\r
   UINT32                     *Id;\r
+  BOOLEAN                    FirstStart;\r
+\r
+  FirstStart = FALSE;\r
 \r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
@@ -323,6 +420,8 @@ HttpBootIp4DxeDriverBindingStart (
   if (!EFI_ERROR (Status)) {\r
     Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);\r
   } else {\r
+    FirstStart = TRUE;\r
+  \r
     //\r
     // Initialize the private data structure.\r
     //\r
@@ -396,7 +495,8 @@ HttpBootIp4DxeDriverBindingStart (
   \r
   Private->Ip4Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));\r
   if (Private->Ip4Nic == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_ERROR;\r
   }\r
   Private->Ip4Nic->Private     = Private;\r
   Private->Ip4Nic->ImageHandle = This->DriverBindingHandle;\r
@@ -513,13 +613,22 @@ HttpBootIp4DxeDriverBindingStart (
   }\r
   \r
   return EFI_SUCCESS;\r
-\r
     \r
 ON_ERROR:\r
-\r
+  if (FirstStart) {\r
+    gBS->UninstallProtocolInterface (\r
+           ControllerHandle,\r
+           &gEfiCallerIdGuid,\r
+           &Private->Id\r
+           );\r
+  }\r
+  \r
   HttpBootDestroyIp4Children (This, Private);\r
   HttpBootConfigFormUnload (Private);\r
-  FreePool (Private);\r
+\r
+  if (FirstStart && Private != NULL) {\r
+    FreePool (Private);\r
+  }\r
 \r
   return Status;\r
 }\r
@@ -782,6 +891,10 @@ HttpBootIp6DxeDriverBindingStart (
   EFI_DEV_PATH               *Node;\r
   EFI_DEVICE_PATH_PROTOCOL   *DevicePath;\r
   UINT32                     *Id;\r
+  BOOLEAN                    Ipv6Available;\r
+  BOOLEAN                    FirstStart;\r
+\r
+  FirstStart = FALSE;\r
   \r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
@@ -795,6 +908,8 @@ HttpBootIp6DxeDriverBindingStart (
   if (!EFI_ERROR (Status)) {\r
     Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);\r
   } else {\r
+    FirstStart = TRUE;\r
+    \r
     //\r
     // Initialize the private data structure.\r
     //\r
@@ -858,6 +973,23 @@ HttpBootIp6DxeDriverBindingStart (
     }\r
       \r
   }\r
+\r
+  //\r
+  // Set IPv6 available flag.\r
+  // \r
+  Status = HttpBootCheckIpv6Support (Private, &Ipv6Available);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Fail to get the data whether UNDI supports IPv6. \r
+    // Set default value to TRUE.\r
+    //\r
+    Ipv6Available = TRUE;\r
+  }\r
+\r
+  if (!Ipv6Available) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_ERROR;\r
+  }\r
   \r
   if (Private->Ip6Nic != NULL) {\r
     //\r
@@ -868,7 +1000,8 @@ HttpBootIp6DxeDriverBindingStart (
   \r
   Private->Ip6Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));\r
   if (Private->Ip6Nic == NULL) {\r
-    return EFI_OUT_OF_RESOURCES;\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_ERROR;\r
   }\r
   Private->Ip6Nic->Private     = Private;\r
   Private->Ip6Nic->ImageHandle = This->DriverBindingHandle;\r
@@ -1011,10 +1144,20 @@ HttpBootIp6DxeDriverBindingStart (
   return EFI_SUCCESS;\r
    \r
 ON_ERROR:\r
+  if (FirstStart) {\r
+    gBS->UninstallProtocolInterface (\r
+           ControllerHandle,\r
+           &gEfiCallerIdGuid,\r
+           &Private->Id\r
+           );\r
+  }\r
 \r
   HttpBootDestroyIp6Children(This, Private);\r
   HttpBootConfigFormUnload (Private);\r
-  FreePool (Private);\r
+\r
+  if (FirstStart && Private != NULL) {\r
+    FreePool (Private);\r
+  }\r
 \r
   return Status;\r
 }\r
index 2c07cf74665fec8380bc51e386239d01ff0ff89e..166bc458f19007937b63e1e29a7b0b24cc94b55b 100644 (file)
@@ -58,6 +58,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include <Protocol/Ip4Config2.h>\r
 #include <Protocol/Ip6Config.h>\r
 #include <Protocol/RamDisk.h>\r
+#include <Protocol/AdapterInformation.h>\r
+\r
 //\r
 // Produced Protocols\r
 //\r
index 4d6c5e5048eca94b8220c36bacf817aab9f4a21b..6d2a7722066620e8971d5d464a71846eabe95686 100644 (file)
@@ -86,7 +86,8 @@
   gEfiRamDiskProtocolGuid                         ## SOMETIMES_CONSUMES\r
   gEfiHiiConfigAccessProtocolGuid                 ## BY_START\r
   gEfiHttpBootCallbackProtocolGuid                ## SOMETIMES_PRODUCES\r
-  \r
+  gEfiAdapterInformationProtocolGuid              ## SOMETIMES_CONSUMES\r
+\r
 [Guids]\r
   ## SOMETIMES_CONSUMES ## GUID # HiiIsConfigHdrMatch   mHttpBootConfigStorageName\r
   ## SOMETIMES_PRODUCES ## GUID # HiiConstructConfigHdr mHttpBootConfigStorageName\r
@@ -95,6 +96,7 @@
   gHttpBootConfigGuid\r
   gEfiVirtualCdGuid            ## SOMETIMES_CONSUMES ## GUID\r
   gEfiVirtualDiskGuid          ## SOMETIMES_CONSUMES ## GUID\r
+  gEfiAdapterInfoUndiIpv6SupportGuid             ## SOMETIMES_CONSUMES ## GUID\r
 \r
 [Pcd]\r
   gEfiNetworkPkgTokenSpaceGuid.PcdAllowHttpConnections       ## CONSUMES  \r