]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
NetworkPkg: Fix PXEv6 boot failure when DhcpBinl offer received.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDriver.c
index 0b2743d1279d72c7410f6b532fd83a8a871f3cef..09c5753ad9e79938f1c129b350c3ad39aa9d8b2f 100644 (file)
@@ -1,7 +1,8 @@
 /** @file\r
   Driver Binding functions implementationfor for UefiPxeBc Driver.\r
 \r
 /** @file\r
   Driver Binding functions implementationfor for UefiPxeBc Driver.\r
 \r
-  Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -441,6 +442,103 @@ PxeBcDestroyIp6Children (
   Private->Mode.Ipv6Available = FALSE;\r
 }\r
 \r
   Private->Mode.Ipv6Available = FALSE;\r
 }\r
 \r
+/**\r
+  Check whether UNDI protocol supports IPv6.\r
+\r
+  @param[in]   ControllerHandle  Controller handle.\r
+  @param[in]   Private           Pointer to PXEBC_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
+PxeBcCheckIpv6Support (\r
+  IN  EFI_HANDLE                   ControllerHandle,\r
+  IN  PXEBC_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
+  // Check whether the UNDI supports IPv6 by AIP protocol.\r
+  //\r
+\r
+  //\r
+  // Get the NIC handle by SNP protocol.\r
+  //  \r
+  Handle = NetLibGetSnpHandle (ControllerHandle, 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
+  return EFI_SUCCESS;\r
+\r
+}\r
 \r
 /**\r
   Create the opened instances based on IPv4.\r
 \r
 /**\r
   Create the opened instances based on IPv4.\r
@@ -644,6 +742,18 @@ PxeBcCreateIp4Children (
   Private->Ip4Nic->Private   = Private;\r
   Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;\r
 \r
   Private->Ip4Nic->Private   = Private;\r
   Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;\r
 \r
+   //\r
+  // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  ControllerHandle,\r
+                  &gEfiIp4Config2ProtocolGuid,\r
+                  (VOID **) &Private->Ip4Config2\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   //\r
   // Create a device path node for Ipv4 virtual nic, and append it.\r
   //\r
   //\r
   // Create a device path node for Ipv4 virtual nic, and append it.\r
   //\r
@@ -951,6 +1061,30 @@ PxeBcCreateIp6Children (
 \r
   Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;\r
 \r
 \r
   Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;\r
 \r
+  if (Ip6ModeData.AddressList != NULL) {\r
+    FreePool (Ip6ModeData.AddressList);\r
+  }\r
+\r
+  if (Ip6ModeData.GroupTable != NULL) {\r
+    FreePool (Ip6ModeData.GroupTable);\r
+  }\r
+\r
+  if (Ip6ModeData.RouteTable != NULL) {\r
+    FreePool (Ip6ModeData.RouteTable);\r
+  }\r
+\r
+  if (Ip6ModeData.NeighborCache != NULL) {\r
+    FreePool (Ip6ModeData.NeighborCache);\r
+  }\r
+\r
+  if (Ip6ModeData.PrefixTable != NULL) {\r
+    FreePool (Ip6ModeData.PrefixTable);\r
+  }\r
+\r
+  if (Ip6ModeData.IcmpTypeList != NULL) {\r
+    FreePool (Ip6ModeData.IcmpTypeList);\r
+  }\r
+\r
   //\r
   // Locate Ip6->Ip6Config and store it for set IPv6 address.\r
   //\r
   //\r
   // Locate Ip6->Ip6Config and store it for set IPv6 address.\r
   //\r
@@ -1056,7 +1190,18 @@ PxeBcCreateIp6Children (
   // Set IPv6 avaiable flag and set default configure data for\r
   // Udp6Read and Ip6 instance.\r
   //\r
   // Set IPv6 avaiable flag and set default configure data for\r
   // Udp6Read and Ip6 instance.\r
   //\r
-  Private->Mode.Ipv6Available     = TRUE;\r
+  Status = PxeBcCheckIpv6Support (ControllerHandle, Private, &Private->Mode.Ipv6Available);\r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Fail to get the data whether UNDI supports IPv6. Set default value.\r
+    //\r
+    Private->Mode.Ipv6Available   = TRUE;\r
+  }\r
+\r
+  if (!Private->Mode.Ipv6Available) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   Udp6CfgData                     = &Private->Udp6CfgData;\r
   Ip6CfgData                      = &Private->Ip6CfgData;\r
 \r
   Udp6CfgData                     = &Private->Udp6CfgData;\r
   Ip6CfgData                      = &Private->Ip6CfgData;\r
 \r
@@ -1353,9 +1498,6 @@ ON_ERROR:
            &gEfiCallerIdGuid,\r
            &Private->Id\r
            );\r
            &gEfiCallerIdGuid,\r
            &Private->Id\r
            );\r
-    if (Private != NULL) {\r
-      FreePool (Private);\r
-    }\r
   }\r
 \r
   if (IpVersion == IP_VERSION_4) {\r
   }\r
 \r
   if (IpVersion == IP_VERSION_4) {\r
@@ -1364,6 +1506,10 @@ ON_ERROR:
     PxeBcDestroyIp6Children (This, Private);\r
   }\r
 \r
     PxeBcDestroyIp6Children (This, Private);\r
   }\r
 \r
+  if (FirstStart && Private != NULL) {\r
+    FreePool (Private);\r
+  }\r
+\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
@@ -1399,7 +1545,6 @@ PxeBcStop (
   EFI_LOAD_FILE_PROTOCOL          *LoadFile;\r
   EFI_STATUS                      Status;\r
   EFI_HANDLE                      NicHandle;\r
   EFI_LOAD_FILE_PROTOCOL          *LoadFile;\r
   EFI_STATUS                      Status;\r
   EFI_HANDLE                      NicHandle;\r
-  BOOLEAN                         IsIpv6;\r
   PXEBC_PRIVATE_PROTOCOL          *Id;\r
 \r
   Private    = NULL;\r
   PXEBC_PRIVATE_PROTOCOL          *Id;\r
 \r
   Private    = NULL;\r
@@ -1407,7 +1552,6 @@ PxeBcStop (
   VirtualNic = NULL;\r
   LoadFile   = NULL;\r
   Id         = NULL;\r
   VirtualNic = NULL;\r
   LoadFile   = NULL;\r
   Id         = NULL;\r
-  IsIpv6     = FALSE;\r
 \r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
 \r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r