]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
UefiCpuPkg/PiSmmCpuDxeSmm: patch "gSmiCr3" with PatchInstructionX86()
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDriver.c
index 4abb6988f51dc125f84f5046b7bdbef04eb1690e..8dd787be1a00aed74701804713b3d7a6ff77ed75 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 - 2011, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2007 - 2018, 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
 #include "PxeBcImpl.h"\r
 \r
 \r
 #include "PxeBcImpl.h"\r
 \r
 \r
-EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {\r
-  PxeBcDriverBindingSupported,\r
-  PxeBcDriverBindingStart,\r
-  PxeBcDriverBindingStop,\r
+EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp4DriverBinding = {\r
+  PxeBcIp4DriverBindingSupported,\r
+  PxeBcIp4DriverBindingStart,\r
+  PxeBcIp4DriverBindingStop,\r
   0xa,\r
   NULL,\r
   NULL\r
 };\r
 \r
   0xa,\r
   NULL,\r
   NULL\r
 };\r
 \r
-//\r
-// PXE_PRIVATE_GUID is only used to keep the relationship between \r
-// NIC handle and virtual child handles.\r
-//\r
-EFI_GUID mPxeBcPrivateGuid = PXEBC_PRIVATE_GUID;\r
-\r
-\r
+EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp6DriverBinding = {\r
+  PxeBcIp6DriverBindingSupported,\r
+  PxeBcIp6DriverBindingStart,\r
+  PxeBcIp6DriverBindingStop,\r
+  0xa,\r
+  NULL,\r
+  NULL\r
+};\r
 \r
 /**\r
   Get the Nic handle using any child handle in the IPv4 stack.\r
 \r
 /**\r
   Get the Nic handle using any child handle in the IPv4 stack.\r
@@ -237,7 +239,7 @@ PxeBcDestroyIp4Children (
     //\r
     gBS->CloseProtocol (\r
            Private->Controller,\r
     //\r
     gBS->CloseProtocol (\r
            Private->Controller,\r
-           &mPxeBcPrivateGuid,\r
+           &gEfiCallerIdGuid,\r
            This->DriverBindingHandle,\r
            Private->Ip4Nic->Controller\r
            );\r
            This->DriverBindingHandle,\r
            Private->Ip4Nic->Controller\r
            );\r
@@ -252,6 +254,7 @@ PxeBcDestroyIp4Children (
            &Private->PxeBc,\r
            NULL\r
            );\r
            &Private->PxeBc,\r
            NULL\r
            );\r
+    FreePool (Private->Ip4Nic->DevicePath);\r
 \r
     if (Private->Snp != NULL) { \r
       //\r
 \r
     if (Private->Snp != NULL) { \r
       //\r
@@ -397,7 +400,7 @@ PxeBcDestroyIp6Children (
     //\r
     gBS->CloseProtocol (\r
            Private->Controller,\r
     //\r
     gBS->CloseProtocol (\r
            Private->Controller,\r
-           &mPxeBcPrivateGuid,\r
+           &gEfiCallerIdGuid,\r
            This->DriverBindingHandle,\r
            Private->Ip6Nic->Controller\r
            );\r
            This->DriverBindingHandle,\r
            Private->Ip6Nic->Controller\r
            );\r
@@ -412,6 +415,8 @@ PxeBcDestroyIp6Children (
            &Private->PxeBc,\r
            NULL\r
            );\r
            &Private->PxeBc,\r
            NULL\r
            );\r
+    FreePool (Private->Ip6Nic->DevicePath);\r
+    \r
     if (Private->Snp != NULL) {\r
       //\r
       // Close SNP from the child virtual handle\r
     if (Private->Snp != NULL) {\r
       //\r
       // Close SNP from the child virtual handle\r
@@ -440,6 +445,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
@@ -643,6 +745,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
@@ -722,7 +836,7 @@ PxeBcCreateIp4Children (
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
-                  &mPxeBcPrivateGuid,\r
+                  &gEfiCallerIdGuid,\r
                   (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   Private->Ip4Nic->Controller,\r
                   (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   Private->Ip4Nic->Controller,\r
@@ -739,7 +853,7 @@ PxeBcCreateIp4Children (
   Udp4CfgData                     = &Private->Udp4CfgData;\r
   Ip4CfgData                      = &Private->Ip4CfgData;\r
 \r
   Udp4CfgData                     = &Private->Udp4CfgData;\r
   Ip4CfgData                      = &Private->Ip4CfgData;\r
 \r
-  Udp4CfgData->AcceptBroadcast    = TRUE;\r
+  Udp4CfgData->AcceptBroadcast    = FALSE;\r
   Udp4CfgData->AcceptAnyPort      = TRUE;\r
   Udp4CfgData->AllowDuplicatePort = TRUE;\r
   Udp4CfgData->TypeOfService      = Mode->ToS;\r
   Udp4CfgData->AcceptAnyPort      = TRUE;\r
   Udp4CfgData->AllowDuplicatePort = TRUE;\r
   Udp4CfgData->TypeOfService      = Mode->ToS;\r
@@ -787,6 +901,7 @@ PxeBcCreateIp6Children (
   EFI_IP6_MODE_DATA               Ip6ModeData;\r
   PXEBC_PRIVATE_PROTOCOL          *Id;\r
   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
   EFI_IP6_MODE_DATA               Ip6ModeData;\r
   PXEBC_PRIVATE_PROTOCOL          *Id;\r
   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
+  UINTN                           Index;\r
 \r
   if (Private->Ip6Nic != NULL) {\r
     //\r
 \r
   if (Private->Ip6Nic != NULL) {\r
     //\r
@@ -829,6 +944,16 @@ PxeBcCreateIp6Children (
     goto ON_ERROR;\r
   }\r
 \r
     goto ON_ERROR;\r
   }\r
 \r
+  //\r
+  // Generate a random IAID for the Dhcp6 assigned address.\r
+  //\r
+  Private->IaId = NET_RANDOM (NetRandomInitSeed ());\r
+  if (Private->Snp != NULL) {\r
+    for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {\r
+      Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));\r
+    }  \r
+  }\r
+\r
   //\r
   // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.\r
   //\r
   //\r
   // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.\r
   //\r
@@ -939,6 +1064,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
@@ -957,7 +1106,7 @@ PxeBcCreateIp6Children (
   ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));\r
   Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;\r
   Ip6Node.Header.SubType  = MSG_IPv6_DP;\r
   ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));\r
   Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;\r
   Ip6Node.Header.SubType  = MSG_IPv6_DP;\r
-  Ip6Node.StaticIpAddress = FALSE;\r
+  Ip6Node.PrefixLength    = IP6_PREFIX_LENGTH;\r
 \r
   SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));\r
 \r
 \r
   SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));\r
 \r
@@ -1030,7 +1179,7 @@ PxeBcCreateIp6Children (
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
-                  &mPxeBcPrivateGuid,\r
+                  &gEfiCallerIdGuid,\r
                   (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   Private->Ip6Nic->Controller,\r
                   (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   Private->Ip6Nic->Controller,\r
@@ -1044,7 +1193,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
@@ -1086,82 +1246,94 @@ PxeBcDriverEntryPoint (
   IN EFI_SYSTEM_TABLE       *SystemTable\r
   )\r
 {\r
   IN EFI_SYSTEM_TABLE       *SystemTable\r
   )\r
 {\r
-  return EfiLibInstallDriverBindingComponentName2 (\r
-           ImageHandle,\r
-           SystemTable,\r
-           &gPxeBcDriverBinding,\r
+  EFI_STATUS  Status;\r
+\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gPxeBcIp4DriverBinding,\r
+             ImageHandle,\r
+             &gPxeBcComponentName,\r
+             &gPxeBcComponentName2\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = EfiLibInstallDriverBindingComponentName2 (\r
+             ImageHandle,\r
+             SystemTable,\r
+             &gPxeBcIp6DriverBinding,\r
+             NULL,\r
+             &gPxeBcComponentName,\r
+             &gPxeBcComponentName2\r
+             );\r
+  if (EFI_ERROR (Status)) {\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
            ImageHandle,\r
            ImageHandle,\r
+           &gEfiDriverBindingProtocolGuid,\r
+           &gPxeBcIp4DriverBinding,\r
+           &gEfiComponentName2ProtocolGuid,\r
+           &gPxeBcComponentName2,\r
+           &gEfiComponentNameProtocolGuid,\r
            &gPxeBcComponentName,\r
            &gPxeBcComponentName,\r
-           &gPxeBcComponentName2\r
+           NULL\r
            );\r
            );\r
-}\r
+  }\r
 \r
 \r
+  return Status;\r
+}\r
 \r
 /**\r
 \r
 /**\r
-  Test to see if this driver supports ControllerHandle. This service\r
-  is called by the EFI boot service ConnectController(). In\r
-  order to make drivers as small as possible, there are a few calling\r
-  restrictions for this service. ConnectController() must\r
-  follow these calling restrictions. If any other agent wishes to call\r
-  Supported() it must also follow these calling restrictions.\r
+  Test to see if this driver supports ControllerHandle. This is the worker function for\r
+  PxeBcIp4(6)DriverBindingSupported.\r
 \r
   @param[in]  This                The pointer to the driver binding protocol.\r
   @param[in]  ControllerHandle    The handle of device to be tested.\r
   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child\r
                                   device to be started.\r
 \r
   @param[in]  This                The pointer to the driver binding protocol.\r
   @param[in]  ControllerHandle    The handle of device to be tested.\r
   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child\r
                                   device to be started.\r
-\r
+  @param[in]  IpVersion           IP_VERSION_4 or IP_VERSION_6.\r
+  \r
   @retval EFI_SUCCESS         This driver supports this device.\r
   @retval EFI_UNSUPPORTED     This driver does not support this device.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
   @retval EFI_SUCCESS         This driver supports this device.\r
   @retval EFI_UNSUPPORTED     This driver does not support this device.\r
 \r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-PxeBcDriverBindingSupported (\r
+PxeBcSupported (\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,\r
+  IN UINT8                        IpVersion\r
   )\r
 {\r
   )\r
 {\r
-  EFI_STATUS                      Ip4Status;\r
-  EFI_STATUS                      Ip6Status;\r
-\r
-  //\r
-  // Try to open the Mtftp4 and Dhcp4 protocol to test whether IPv4 stack is ready.\r
-  //\r
-  Ip4Status = gBS->OpenProtocol (\r
-                     ControllerHandle,\r
-                     &gEfiDhcp4ServiceBindingProtocolGuid,\r
-                     NULL,\r
-                     This->DriverBindingHandle,\r
-                     ControllerHandle,\r
-                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                     );\r
-  if (!EFI_ERROR (Ip4Status)) {\r
-    Ip4Status = gBS->OpenProtocol (\r
-                       ControllerHandle,\r
-                       &gEfiMtftp4ServiceBindingProtocolGuid,\r
-                       NULL,\r
-                       This->DriverBindingHandle,\r
-                       ControllerHandle,\r
-                       EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                       );\r
+  EFI_STATUS                      Status;\r
+  EFI_GUID                        *DhcpServiceBindingGuid;\r
+  EFI_GUID                        *MtftpServiceBindingGuid;\r
+  \r
+  if (IpVersion == IP_VERSION_4) {\r
+    DhcpServiceBindingGuid  = &gEfiDhcp4ServiceBindingProtocolGuid;\r
+    MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid;\r
+  } else {\r
+    DhcpServiceBindingGuid  = &gEfiDhcp6ServiceBindingProtocolGuid;\r
+    MtftpServiceBindingGuid = &gEfiMtftp6ServiceBindingProtocolGuid;\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  // Try to open the Mtftp6 and Dhcp6 protocol to test whether IPv4 stack is ready.\r
+  // Try to open the Mtftp and Dhcp protocol to test whether IP stack is ready.\r
   //\r
   //\r
-  Ip6Status = gBS->OpenProtocol (\r
+  Status = gBS->OpenProtocol (\r
                      ControllerHandle,\r
                      ControllerHandle,\r
-                     &gEfiDhcp6ServiceBindingProtocolGuid,\r
+                     DhcpServiceBindingGuid,\r
                      NULL,\r
                      This->DriverBindingHandle,\r
                      ControllerHandle,\r
                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
                      );\r
                      NULL,\r
                      This->DriverBindingHandle,\r
                      ControllerHandle,\r
                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
                      );\r
-  if (!EFI_ERROR (Ip6Status)) {\r
-    Ip6Status = gBS->OpenProtocol (\r
+  if (!EFI_ERROR (Status)) {\r
+    Status = gBS->OpenProtocol (\r
                        ControllerHandle,\r
                        ControllerHandle,\r
-                       &gEfiMtftp6ServiceBindingProtocolGuid,\r
+                       MtftpServiceBindingGuid,\r
                        NULL,\r
                        This->DriverBindingHandle,\r
                        ControllerHandle,\r
                        NULL,\r
                        This->DriverBindingHandle,\r
                        ControllerHandle,\r
@@ -1170,28 +1342,25 @@ PxeBcDriverBindingSupported (
   }\r
 \r
   //\r
   }\r
 \r
   //\r
-  // It's unsupported case if both stack are not ready.\r
+  // It's unsupported case if IP stack are not ready.\r
   //\r
   //\r
-  if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {\r
+  if (EFI_ERROR (Status)) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
 /**\r
-  Start this driver on ControllerHandle. This service is called by the\r
-  EFI boot service ConnectController(). In order to make\r
-  drivers as small as possible, there are a few calling restrictions for\r
-  this service. ConnectController() must follow these\r
-  calling restrictions. If any other agent wishes to call Start() it\r
-  must also follow these calling restrictions.\r
+  Start this driver on ControllerHandle. This is the worker function for\r
+  PxeBcIp4(6)DriverBindingStart.\r
 \r
   @param[in]  This                 The pointer to the driver binding protocol.\r
   @param[in]  ControllerHandle     The handle of device to be started.\r
   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child\r
                                    device to be started.\r
 \r
   @param[in]  This                 The pointer to the driver binding protocol.\r
   @param[in]  ControllerHandle     The handle of device to be started.\r
   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child\r
                                    device to be started.\r
+  @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.\r
+\r
 \r
   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.\r
   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.\r
 \r
   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.\r
   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.\r
@@ -1200,21 +1369,22 @@ PxeBcDriverBindingSupported (
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-PxeBcDriverBindingStart (\r
+PxeBcStart (\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,\r
+  IN UINT8                        IpVersion\r
   )\r
 {\r
   PXEBC_PRIVATE_DATA              *Private;\r
   EFI_STATUS                      Status;\r
   )\r
 {\r
   PXEBC_PRIVATE_DATA              *Private;\r
   EFI_STATUS                      Status;\r
-  EFI_STATUS                      Ip4Status;\r
-  EFI_STATUS                      Ip6Status;\r
   PXEBC_PRIVATE_PROTOCOL          *Id;\r
   PXEBC_PRIVATE_PROTOCOL          *Id;\r
+  BOOLEAN                         FirstStart;\r
 \r
 \r
+  FirstStart = FALSE;\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
-                  &mPxeBcPrivateGuid,\r
+                  &gEfiCallerIdGuid,\r
                   (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   ControllerHandle,\r
                   (VOID **) &Id,\r
                   This->DriverBindingHandle,\r
                   ControllerHandle,\r
@@ -1226,6 +1396,7 @@ PxeBcDriverBindingStart (
     //\r
     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);\r
   } else {\r
     //\r
     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);\r
   } else {\r
+    FirstStart = TRUE;\r
     //\r
     // If the driver has not been started yet, it should do initialization.\r
     //\r
     //\r
     // If the driver has not been started yet, it should do initialization.\r
     //\r
@@ -1282,10 +1453,13 @@ PxeBcDriverBindingStart (
 \r
     //\r
     // Install PxeBaseCodePrivate protocol onto the real NIC handler.\r
 \r
     //\r
     // Install PxeBaseCodePrivate protocol onto the real NIC handler.\r
+    // PxeBaseCodePrivate protocol is only used to keep the relationship between \r
+    // NIC handle and virtual child handles.\r
+    // gEfiCallerIdGuid will be used as its protocol guid.\r
     //\r
     Status = gBS->InstallProtocolInterface (\r
                     &ControllerHandle,\r
     //\r
     Status = gBS->InstallProtocolInterface (\r
                     &ControllerHandle,\r
-                    &mPxeBcPrivateGuid,\r
+                    &gEfiCallerIdGuid,\r
                     EFI_NATIVE_INTERFACE,\r
                     &Private->Id\r
                     );\r
                     EFI_NATIVE_INTERFACE,\r
                     &Private->Id\r
                     );\r
@@ -1299,17 +1473,18 @@ PxeBcDriverBindingStart (
     NetLibGetSnpHandle(ControllerHandle, &Private->Snp);    \r
   }\r
 \r
     NetLibGetSnpHandle(ControllerHandle, &Private->Snp);    \r
   }\r
 \r
-  //\r
-  // Try to create virtual NIC handle for IPv4.\r
-  //\r
-  Ip4Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);\r
-\r
-  //\r
-  // Try to create virtual NIC handle for IPv6.\r
-  //\r
-  Ip6Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);\r
-\r
-  if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {\r
+  if (IpVersion == IP_VERSION_4) {\r
+    //\r
+    // Try to create virtual NIC handle for IPv4.\r
+    //\r
+    Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);\r
+  } else {\r
+    //\r
+    // Try to create virtual NIC handle for IPv6.\r
+    //\r
+    Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);\r
+  }\r
+  if (EFI_ERROR (Status)) {\r
     //\r
     // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.\r
     //\r
     //\r
     // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.\r
     //\r
@@ -1320,32 +1495,38 @@ PxeBcDriverBindingStart (
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
-  gBS->UninstallProtocolInterface (\r
-         ControllerHandle,\r
-         &mPxeBcPrivateGuid,\r
-         &Private->Id\r
-         );\r
-  PxeBcDestroyIp4Children (This, Private);\r
-  PxeBcDestroyIp6Children (This, Private);\r
-  FreePool (Private);\r
+  if (FirstStart) {\r
+    gBS->UninstallProtocolInterface (\r
+           ControllerHandle,\r
+           &gEfiCallerIdGuid,\r
+           &Private->Id\r
+           );\r
+  }\r
+\r
+  if (IpVersion == IP_VERSION_4) {\r
+    PxeBcDestroyIp4Children (This, Private);\r
+  } else {\r
+    PxeBcDestroyIp6Children (This, Private);\r
+  }\r
+\r
+  if (FirstStart && Private != NULL) {\r
+    FreePool (Private);\r
+  }\r
 \r
   return Status;\r
 }\r
 \r
 \r
 /**\r
 \r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Stop this driver on ControllerHandle. This service is called by the\r
-  EFI boot service DisconnectController(). In order to\r
-  make drivers as small as possible, there are a few calling\r
-  restrictions for this service. DisconnectController()\r
-  must follow these calling restrictions. If any other agent wishes\r
-  to call Stop() it must also follow these calling restrictions.\r
+  Stop this driver on ControllerHandle. This is the worker function for\r
+  PxeBcIp4(6)DriverBindingStop.\r
 \r
   @param[in]  This              Protocol instance pointer.\r
   @param[in]  ControllerHandle  Handle of device to stop driver on.\r
   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
                                 children is zero stop the entire bus driver.\r
   @param[in]  ChildHandleBuffer List of Child Handles to Stop.\r
 \r
   @param[in]  This              Protocol instance pointer.\r
   @param[in]  ControllerHandle  Handle of device to stop driver on.\r
   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
                                 children is zero stop the entire bus driver.\r
   @param[in]  ChildHandleBuffer List of Child Handles to Stop.\r
+  @param[in]  IpVersion         IP_VERSION_4 or IP_VERSION_6.\r
 \r
   @retval EFI_SUCCESS           This driver was removed ControllerHandle.\r
   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
 \r
   @retval EFI_SUCCESS           This driver was removed ControllerHandle.\r
   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
@@ -1354,11 +1535,12 @@ ON_ERROR:
 **/\r
 EFI_STATUS\r
 EFIAPI\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-PxeBcDriverBindingStop (\r
+PxeBcStop (\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
   IN UINTN                        NumberOfChildren,\r
   IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
   IN UINTN                        NumberOfChildren,\r
-  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  IN EFI_HANDLE                   *ChildHandleBuffer,\r
+  IN UINT8                        IpVersion\r
   )\r
 {\r
   PXEBC_PRIVATE_DATA              *Private;\r
   )\r
 {\r
   PXEBC_PRIVATE_DATA              *Private;\r
@@ -1366,7 +1548,6 @@ PxeBcDriverBindingStop (
   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
@@ -1374,7 +1555,6 @@ PxeBcDriverBindingStop (
   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
@@ -1388,14 +1568,13 @@ PxeBcDriverBindingStop (
     //\r
     // Get the Nic handle by any pass-over service child handle.\r
     //\r
     //\r
     // Get the Nic handle by any pass-over service child handle.\r
     //\r
-    NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);\r
-    if (NicHandle == NULL) {\r
+    if (IpVersion == IP_VERSION_4) {\r
+      NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);\r
+    } else {\r
       NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);\r
       NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);\r
-      if (NicHandle == NULL) {\r
-        return EFI_DEVICE_ERROR;\r
-      } else {\r
-        IsIpv6 = TRUE;\r
-      }\r
+    }\r
+    if (NicHandle == NULL) {\r
+      return EFI_SUCCESS;\r
     }\r
 \r
     //\r
     }\r
 \r
     //\r
@@ -1403,7 +1582,7 @@ PxeBcDriverBindingStop (
     //\r
     Status = gBS->OpenProtocol (\r
                     NicHandle,\r
     //\r
     Status = gBS->OpenProtocol (\r
                     NicHandle,\r
-                    &mPxeBcPrivateGuid,\r
+                    &gEfiCallerIdGuid,\r
                     (VOID **) &Id,\r
                     This->DriverBindingHandle,\r
                     ControllerHandle,\r
                     (VOID **) &Id,\r
                     This->DriverBindingHandle,\r
                     ControllerHandle,\r
@@ -1433,10 +1612,6 @@ PxeBcDriverBindingStop (
     VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);\r
     Private    = VirtualNic->Private;\r
     NicHandle  = Private->Controller;\r
     VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);\r
     Private    = VirtualNic->Private;\r
     NicHandle  = Private->Controller;\r
-\r
-    if (Private->Ip6Nic == VirtualNic) {\r
-      IsIpv6   = TRUE;\r
-    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -1448,18 +1623,18 @@ PxeBcDriverBindingStop (
   }\r
 \r
 \r
   }\r
 \r
 \r
-  if (Private->Ip4Nic != NULL && !IsIpv6) {\r
+  if (Private->Ip4Nic != NULL && IpVersion == IP_VERSION_4) {\r
     PxeBcDestroyIp4Children (This, Private);\r
   }\r
 \r
     PxeBcDestroyIp4Children (This, Private);\r
   }\r
 \r
-  if (Private->Ip6Nic != NULL && IsIpv6) {\r
+  if (Private->Ip6Nic != NULL && IpVersion == IP_VERSION_6) {\r
     PxeBcDestroyIp6Children (This, Private);\r
   }\r
 \r
   if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
     gBS->UninstallProtocolInterface (\r
            NicHandle,\r
     PxeBcDestroyIp6Children (This, Private);\r
   }\r
 \r
   if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
     gBS->UninstallProtocolInterface (\r
            NicHandle,\r
-           &mPxeBcPrivateGuid,\r
+           &gEfiCallerIdGuid,\r
            &Private->Id\r
            );\r
     FreePool (Private);\r
            &Private->Id\r
            );\r
     FreePool (Private);\r
@@ -1467,3 +1642,211 @@ PxeBcDriverBindingStop (
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. This service\r
+  is called by the EFI boot service ConnectController(). In\r
+  order to make drivers as small as possible, there are a few calling\r
+  restrictions for this service. ConnectController() must\r
+  follow these calling restrictions. If any other agent wishes to call\r
+  Supported() it must also follow these calling restrictions.\r
+\r
+  @param[in]  This                The pointer to the driver binding protocol.\r
+  @param[in]  ControllerHandle    The handle of device to be tested.\r
+  @param[in]  RemainingDevicePath Optional parameter used to pick a specific child\r
+                                  device to be started.\r
+\r
+  @retval EFI_SUCCESS         This driver supports this device.\r
+  @retval EFI_UNSUPPORTED     This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcIp4DriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  return PxeBcSupported (\r
+           This,\r
+           ControllerHandle,\r
+           RemainingDevicePath,\r
+           IP_VERSION_4\r
+           );\r
+}\r
+\r
+/**\r
+  Start this driver on ControllerHandle. This service is called by the\r
+  EFI boot service ConnectController(). In order to make\r
+  drivers as small as possible, there are a few calling restrictions for\r
+  this service. ConnectController() must follow these\r
+  calling restrictions. If any other agent wishes to call Start() it\r
+  must also follow these calling restrictions.\r
+\r
+  @param[in]  This                 The pointer to the driver binding protocol.\r
+  @param[in]  ControllerHandle     The handle of device to be started.\r
+  @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child\r
+                                   device to be started.\r
+\r
+  @retval EFI_SUCCESS          This driver is installed to ControllerHandle.\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.\r
+  @retval other                This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcIp4DriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  return PxeBcStart (\r
+           This,\r
+           ControllerHandle,\r
+           RemainingDevicePath,\r
+           IP_VERSION_4\r
+           );\r
+}\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. This service is called by the\r
+  EFI boot service DisconnectController(). In order to\r
+  make drivers as small as possible, there are a few calling\r
+  restrictions for this service. DisconnectController()\r
+  must follow these calling restrictions. If any other agent wishes\r
+  to call Stop() it must also follow these calling restrictions.\r
+\r
+  @param[in]  This              Protocol instance pointer.\r
+  @param[in]  ControllerHandle  Handle of device to stop driver on\r
+  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                                children is zero stop the entire bus driver.\r
+  @param[in]  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS           This driver is removed ControllerHandle\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
+  @retval Others                This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcIp4DriverBindingStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  return PxeBcStop (\r
+           This,\r
+           ControllerHandle,\r
+           NumberOfChildren,\r
+           ChildHandleBuffer,\r
+           IP_VERSION_4\r
+           );\r
+}\r
+\r
+/**\r
+  Test to see if this driver supports ControllerHandle. This service\r
+  is called by the EFI boot service ConnectController(). In\r
+  order to make drivers as small as possible, there are a few calling\r
+  restrictions for this service. ConnectController() must\r
+  follow these calling restrictions. If any other agent wishes to call\r
+  Supported() it must also follow these calling restrictions.\r
+\r
+  @param[in]  This                The pointer to the driver binding protocol.\r
+  @param[in]  ControllerHandle    The handle of device to be tested.\r
+  @param[in]  RemainingDevicePath Optional parameter use to pick a specific child\r
+                                  device to be started.\r
+\r
+  @retval EFI_SUCCESS         This driver supports this device.\r
+  @retval EFI_UNSUPPORTED     This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcIp6DriverBindingSupported (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  return PxeBcSupported (\r
+           This,\r
+           ControllerHandle,\r
+           RemainingDevicePath,\r
+           IP_VERSION_6\r
+           );\r
+}\r
+\r
+/**\r
+  Start this driver on ControllerHandle. This service is called by the\r
+  EFI boot service ConnectController(). In order to make\r
+  drivers as small as possible, there are a few calling restrictions for\r
+  this service. ConnectController() must follow these\r
+  calling restrictions. If any other agent wishes to call Start() it\r
+  must also follow these calling restrictions.\r
+\r
+  @param[in]  This                 The pointer to the driver binding protocol.\r
+  @param[in]  ControllerHandle     The handle of device to be started.\r
+  @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child\r
+                                   device to be started.\r
+\r
+  @retval EFI_SUCCESS          This driver is installed to ControllerHandle.\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.\r
+  @retval other                This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcIp6DriverBindingStart (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
+  )\r
+{\r
+  return PxeBcStart (\r
+           This,\r
+           ControllerHandle,\r
+           RemainingDevicePath,\r
+           IP_VERSION_6\r
+           );\r
+}\r
+\r
+/**\r
+  Stop this driver on ControllerHandle. This service is called by the\r
+  EFI boot service DisconnectController(). In order to\r
+  make drivers as small as possible, there are a few calling\r
+  restrictions for this service. DisconnectController()\r
+  must follow these calling restrictions. If any other agent wishes\r
+  to call Stop() it must also follow these calling restrictions.\r
+\r
+  @param[in]  This              Protocol instance pointer.\r
+  @param[in]  ControllerHandle  Handle of device to stop driver on\r
+  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                                children is zero stop the entire bus driver.\r
+  @param[in]  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS           This driver is removed ControllerHandle\r
+  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.\r
+  @retval Others                This driver was not removed from this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PxeBcIp6DriverBindingStop (\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
+  IN EFI_HANDLE                   ControllerHandle,\r
+  IN UINTN                        NumberOfChildren,\r
+  IN EFI_HANDLE                   *ChildHandleBuffer\r
+  )\r
+{\r
+  return PxeBcStop (\r
+           This,\r
+           ControllerHandle,\r
+           NumberOfChildren,\r
+           ChildHandleBuffer,\r
+           IP_VERSION_6\r
+           );\r
+}\r