Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Fu Siyuan <siyuan.fu@intel.com> Reviewed-by: Sriram Subramanian <sriram-s@hpe.com> Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com>
		
			
				
	
	
		
			1853 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1853 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Driver Binding functions implementationfor for UefiPxeBc Driver.
 | 
						|
 | 
						|
  (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
 | 
						|
  Copyright (c) 2007 - 2018, 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
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php.
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include "PxeBcImpl.h"
 | 
						|
 | 
						|
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp4DriverBinding = {
 | 
						|
  PxeBcIp4DriverBindingSupported,
 | 
						|
  PxeBcIp4DriverBindingStart,
 | 
						|
  PxeBcIp4DriverBindingStop,
 | 
						|
  0xa,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp6DriverBinding = {
 | 
						|
  PxeBcIp6DriverBindingSupported,
 | 
						|
  PxeBcIp6DriverBindingStart,
 | 
						|
  PxeBcIp6DriverBindingStop,
 | 
						|
  0xa,
 | 
						|
  NULL,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
/**
 | 
						|
  Get the Nic handle using any child handle in the IPv4 stack.
 | 
						|
 | 
						|
  @param[in]  ControllerHandle    Pointer to child handle over IPv4.
 | 
						|
 | 
						|
  @return NicHandle               The pointer to the Nic handle.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_HANDLE
 | 
						|
PxeBcGetNicByIp4Children (
 | 
						|
  IN EFI_HANDLE                 ControllerHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HANDLE                    NicHandle;
 | 
						|
 | 
						|
  NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
 | 
						|
  if (NicHandle == NULL) {
 | 
						|
    NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
 | 
						|
    if (NicHandle == NULL) {
 | 
						|
      NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
 | 
						|
      if (NicHandle == NULL) {
 | 
						|
        NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
 | 
						|
        if (NicHandle == NULL) {
 | 
						|
          NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
 | 
						|
          if (NicHandle == NULL) {
 | 
						|
            return NULL;
 | 
						|
          }
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NicHandle;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Get the Nic handle using any child handle in the IPv6 stack.
 | 
						|
 | 
						|
  @param[in]  ControllerHandle    Pointer to child handle over IPv6.
 | 
						|
 | 
						|
  @return NicHandle               The pointer to the Nic handle.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_HANDLE
 | 
						|
PxeBcGetNicByIp6Children (
 | 
						|
  IN EFI_HANDLE                  ControllerHandle
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_HANDLE                     NicHandle;
 | 
						|
 | 
						|
  NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp6ProtocolGuid);
 | 
						|
  if (NicHandle == NULL) {
 | 
						|
    NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
 | 
						|
    if (NicHandle == NULL) {
 | 
						|
      NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
 | 
						|
      if (NicHandle == NULL) {
 | 
						|
        NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp6ProtocolGuid);
 | 
						|
        if (NicHandle == NULL) {
 | 
						|
          return NULL;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return NicHandle;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Destroy the opened instances based on IPv4.
 | 
						|
 | 
						|
  @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
 | 
						|
  @param[in]  Private           Pointer to PXEBC_PRIVATE_DATA.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PxeBcDestroyIp4Children (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN PXEBC_PRIVATE_DATA           *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT(Private != NULL);
 | 
						|
 | 
						|
  if (Private->ArpChild != NULL) {
 | 
						|
    //
 | 
						|
    // Close Arp for PxeBc->Arp and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Private->ArpChild,
 | 
						|
           &gEfiArpProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Private->Controller
 | 
						|
           );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiArpServiceBindingProtocolGuid,
 | 
						|
      Private->ArpChild
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Ip4Child != NULL) {
 | 
						|
    //
 | 
						|
    // Close Ip4 for background ICMP error message and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Private->Ip4Child,
 | 
						|
           &gEfiIp4ProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Private->Controller
 | 
						|
           );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiIp4ServiceBindingProtocolGuid,
 | 
						|
      Private->Ip4Child
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Udp4WriteChild != NULL) {
 | 
						|
    //
 | 
						|
    // Close Udp4 for PxeBc->UdpWrite and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Private->Udp4WriteChild,
 | 
						|
           &gEfiUdp4ProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Private->Controller
 | 
						|
           );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiUdp4ServiceBindingProtocolGuid,
 | 
						|
      Private->Udp4WriteChild
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Udp4ReadChild != NULL) {
 | 
						|
    //
 | 
						|
    // Close Udp4 for PxeBc->UdpRead and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Private->Udp4ReadChild,
 | 
						|
          &gEfiUdp4ProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Private->Controller
 | 
						|
          );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiUdp4ServiceBindingProtocolGuid,
 | 
						|
      Private->Udp4ReadChild
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Mtftp4Child != NULL) {
 | 
						|
    //
 | 
						|
    // Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Private->Mtftp4Child,
 | 
						|
          &gEfiMtftp4ProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Private->Controller
 | 
						|
          );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
      Private->Mtftp4Child
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Dhcp4Child != NULL) {
 | 
						|
    //
 | 
						|
    // Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Private->Dhcp4Child,
 | 
						|
          &gEfiDhcp4ProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Private->Controller
 | 
						|
          );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiDhcp4ServiceBindingProtocolGuid,
 | 
						|
      Private->Dhcp4Child
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Ip4Nic != NULL) {
 | 
						|
    //
 | 
						|
    // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Private->Controller,
 | 
						|
           &gEfiCallerIdGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Private->Ip4Nic->Controller
 | 
						|
           );
 | 
						|
 | 
						|
    gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
           Private->Ip4Nic->Controller,
 | 
						|
           &gEfiDevicePathProtocolGuid,
 | 
						|
           Private->Ip4Nic->DevicePath,
 | 
						|
           &gEfiLoadFileProtocolGuid,
 | 
						|
           &Private->Ip4Nic->LoadFile,
 | 
						|
           &gEfiPxeBaseCodeProtocolGuid,
 | 
						|
           &Private->PxeBc,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
    FreePool (Private->Ip4Nic->DevicePath);
 | 
						|
 | 
						|
    if (Private->Snp != NULL) { 
 | 
						|
      //
 | 
						|
      // Close SNP from the child virtual handle
 | 
						|
      //
 | 
						|
      gBS->CloseProtocol (
 | 
						|
             Private->Ip4Nic->Controller,
 | 
						|
             &gEfiSimpleNetworkProtocolGuid,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             Private->Ip4Nic->Controller
 | 
						|
             );
 | 
						|
             
 | 
						|
      gBS->UninstallProtocolInterface (
 | 
						|
             Private->Ip4Nic->Controller,
 | 
						|
             &gEfiSimpleNetworkProtocolGuid,
 | 
						|
             Private->Snp
 | 
						|
             );
 | 
						|
    }
 | 
						|
    FreePool (Private->Ip4Nic);
 | 
						|
  }
 | 
						|
 | 
						|
  Private->ArpChild         = NULL;
 | 
						|
  Private->Ip4Child         = NULL;
 | 
						|
  Private->Udp4WriteChild   = NULL;
 | 
						|
  Private->Udp4ReadChild    = NULL;
 | 
						|
  Private->Mtftp4Child      = NULL;
 | 
						|
  Private->Dhcp4Child       = NULL;
 | 
						|
  Private->Ip4Nic           = NULL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Destroy the opened instances based on IPv6.
 | 
						|
 | 
						|
  @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
 | 
						|
  @param[in]  Private           Pointer to PXEBC_PRIVATE_DATA.
 | 
						|
 | 
						|
**/
 | 
						|
VOID
 | 
						|
PxeBcDestroyIp6Children (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN PXEBC_PRIVATE_DATA           *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  ASSERT(Private != NULL);
 | 
						|
 | 
						|
  if (Private->Ip6Child != NULL) {
 | 
						|
    //
 | 
						|
    // Close Ip6 for Ip6->Ip6Config and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Private->Ip6Child,
 | 
						|
          &gEfiIp6ProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Private->Controller
 | 
						|
          );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiIp6ServiceBindingProtocolGuid,
 | 
						|
      Private->Ip6Child
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Udp6WriteChild != NULL) {
 | 
						|
    //
 | 
						|
    // Close Udp6 for PxeBc->UdpWrite and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Private->Udp6WriteChild,
 | 
						|
           &gEfiUdp6ProtocolGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Private->Controller
 | 
						|
           );
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiUdp6ServiceBindingProtocolGuid,
 | 
						|
      Private->Udp6WriteChild
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Udp6ReadChild != NULL) {
 | 
						|
    //
 | 
						|
    // Close Udp6 for PxeBc->UdpRead and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Private->Udp6ReadChild,
 | 
						|
          &gEfiUdp6ProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Private->Controller
 | 
						|
          );
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiUdp6ServiceBindingProtocolGuid,
 | 
						|
      Private->Udp6ReadChild
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Mtftp6Child != NULL) {
 | 
						|
    //
 | 
						|
    // Close Mtftp6 for PxeBc->Mtftp and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Private->Mtftp6Child,
 | 
						|
          &gEfiMtftp6ProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Private->Controller
 | 
						|
          );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiMtftp6ServiceBindingProtocolGuid,
 | 
						|
      Private->Mtftp6Child
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Dhcp6Child != NULL) {
 | 
						|
    //
 | 
						|
    // Close Dhcp6 for PxeBc->Dhcp and destroy the instance.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
          Private->Dhcp6Child,
 | 
						|
          &gEfiDhcp6ProtocolGuid,
 | 
						|
          This->DriverBindingHandle,
 | 
						|
          Private->Controller
 | 
						|
          );
 | 
						|
 | 
						|
    NetLibDestroyServiceChild (
 | 
						|
      Private->Controller,
 | 
						|
      This->DriverBindingHandle,
 | 
						|
      &gEfiDhcp6ServiceBindingProtocolGuid,
 | 
						|
      Private->Dhcp6Child
 | 
						|
      );
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Ip6Nic != NULL) {
 | 
						|
    //
 | 
						|
    // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
 | 
						|
    //
 | 
						|
    gBS->CloseProtocol (
 | 
						|
           Private->Controller,
 | 
						|
           &gEfiCallerIdGuid,
 | 
						|
           This->DriverBindingHandle,
 | 
						|
           Private->Ip6Nic->Controller
 | 
						|
           );
 | 
						|
 | 
						|
    gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
           Private->Ip6Nic->Controller,
 | 
						|
           &gEfiDevicePathProtocolGuid,
 | 
						|
           Private->Ip6Nic->DevicePath,
 | 
						|
           &gEfiLoadFileProtocolGuid,
 | 
						|
           &Private->Ip6Nic->LoadFile,
 | 
						|
           &gEfiPxeBaseCodeProtocolGuid,
 | 
						|
           &Private->PxeBc,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
    FreePool (Private->Ip6Nic->DevicePath);
 | 
						|
    
 | 
						|
    if (Private->Snp != NULL) {
 | 
						|
      //
 | 
						|
      // Close SNP from the child virtual handle
 | 
						|
      //
 | 
						|
      gBS->CloseProtocol (
 | 
						|
             Private->Ip6Nic->Controller,
 | 
						|
             &gEfiSimpleNetworkProtocolGuid,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             Private->Ip6Nic->Controller
 | 
						|
             );
 | 
						|
      gBS->UninstallProtocolInterface (
 | 
						|
             Private->Ip6Nic->Controller,
 | 
						|
             &gEfiSimpleNetworkProtocolGuid,
 | 
						|
             Private->Snp
 | 
						|
             );
 | 
						|
    }
 | 
						|
    FreePool (Private->Ip6Nic);
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Ip6Child           = NULL;
 | 
						|
  Private->Udp6WriteChild     = NULL;
 | 
						|
  Private->Udp6ReadChild      = NULL;
 | 
						|
  Private->Mtftp6Child        = NULL;
 | 
						|
  Private->Dhcp6Child         = NULL;
 | 
						|
  Private->Ip6Nic             = NULL;
 | 
						|
  Private->Mode.Ipv6Available = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Check whether UNDI protocol supports IPv6.
 | 
						|
 | 
						|
  @param[in]   ControllerHandle  Controller handle.
 | 
						|
  @param[in]   Private           Pointer to PXEBC_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
 | 
						|
PxeBcCheckIpv6Support (
 | 
						|
  IN  EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN  PXEBC_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;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Check whether the UNDI supports IPv6 by AIP protocol.
 | 
						|
  //
 | 
						|
 | 
						|
  //
 | 
						|
  // Get the NIC handle by SNP protocol.
 | 
						|
  //  
 | 
						|
  Handle = NetLibGetSnpHandle (ControllerHandle, 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;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Create the opened instances based on IPv4.
 | 
						|
 | 
						|
  @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
 | 
						|
  @param[in]  ControllerHandle  Handle of the child to destroy.
 | 
						|
  @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The instances based on IPv4 were all created successfully.
 | 
						|
  @retval Others                An unexpected error occurred.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PxeBcCreateIp4Children (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN PXEBC_PRIVATE_DATA           *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  IPv4_DEVICE_PATH                Ip4Node;
 | 
						|
  EFI_PXE_BASE_CODE_MODE          *Mode;
 | 
						|
  EFI_UDP4_CONFIG_DATA            *Udp4CfgData;
 | 
						|
  EFI_IP4_CONFIG_DATA             *Ip4CfgData;
 | 
						|
  EFI_IP4_MODE_DATA               Ip4ModeData;
 | 
						|
  PXEBC_PRIVATE_PROTOCOL          *Id;
 | 
						|
  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
 | 
						|
 | 
						|
  if (Private->Ip4Nic != NULL) {
 | 
						|
    //
 | 
						|
    // Already created before.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiDhcp4ServiceBindingProtocolGuid,
 | 
						|
             &Private->Dhcp4Child
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Dhcp4Child,
 | 
						|
                  &gEfiDhcp4ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Dhcp4,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiMtftp4ServiceBindingProtocolGuid,
 | 
						|
             &Private->Mtftp4Child
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Mtftp4Child,
 | 
						|
                  &gEfiMtftp4ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Mtftp4,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiUdp4ServiceBindingProtocolGuid,
 | 
						|
             &Private->Udp4ReadChild
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Udp4ReadChild,
 | 
						|
                  &gEfiUdp4ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Udp4Read,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiUdp4ServiceBindingProtocolGuid,
 | 
						|
             &Private->Udp4WriteChild
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Udp4WriteChild,
 | 
						|
                  &gEfiUdp4ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Udp4Write,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Arp child and open Arp protocol for PxeBc->Arp.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiArpServiceBindingProtocolGuid,
 | 
						|
             &Private->ArpChild
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->ArpChild,
 | 
						|
                  &gEfiArpProtocolGuid,
 | 
						|
                  (VOID **) &Private->Arp,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Ip4 child and open Ip4 protocol for background ICMP packets.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiIp4ServiceBindingProtocolGuid,
 | 
						|
             &Private->Ip4Child
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Ip4Child,
 | 
						|
                  &gEfiIp4ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Ip4,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get max packet size from Ip4 to calculate block size for Tftp later.
 | 
						|
  //
 | 
						|
  Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;
 | 
						|
 | 
						|
  Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
 | 
						|
  if (Private->Ip4Nic == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Ip4Nic->Private   = Private;
 | 
						|
  Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
 | 
						|
 | 
						|
   //
 | 
						|
  // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  ControllerHandle,
 | 
						|
                  &gEfiIp4Config2ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Ip4Config2
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create a device path node for Ipv4 virtual nic, and append it.
 | 
						|
  //
 | 
						|
  ZeroMem (&Ip4Node, sizeof (IPv4_DEVICE_PATH));
 | 
						|
  Ip4Node.Header.Type     = MESSAGING_DEVICE_PATH;
 | 
						|
  Ip4Node.Header.SubType  = MSG_IPv4_DP;
 | 
						|
  Ip4Node.StaticIpAddress = FALSE;
 | 
						|
 | 
						|
  SetDevicePathNodeLength (&Ip4Node.Header, sizeof (Ip4Node));
 | 
						|
 | 
						|
  Private->Ip4Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip4Node.Header);
 | 
						|
 | 
						|
  if (Private->Ip4Nic->DevicePath == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    &Private->Ip4Nic->LoadFile,
 | 
						|
    &gLoadFileProtocolTemplate,
 | 
						|
    sizeof (EFI_LOAD_FILE_PROTOCOL)
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Create a new handle for IPv4 virtual nic,
 | 
						|
  // and install PxeBaseCode, LoadFile and DevicePath protocols.
 | 
						|
  //
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &Private->Ip4Nic->Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  Private->Ip4Nic->DevicePath,
 | 
						|
                  &gEfiLoadFileProtocolGuid,
 | 
						|
                  &Private->Ip4Nic->LoadFile,
 | 
						|
                  &gEfiPxeBaseCodeProtocolGuid,
 | 
						|
                  &Private->PxeBc,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Snp != NULL) {
 | 
						|
    //
 | 
						|
    // Install SNP protocol on purpose is for some OS loader backward
 | 
						|
    // compatibility consideration.
 | 
						|
    //
 | 
						|
    Status = gBS->InstallProtocolInterface (
 | 
						|
                    &Private->Ip4Nic->Controller,
 | 
						|
                    &gEfiSimpleNetworkProtocolGuid,
 | 
						|
                    EFI_NATIVE_INTERFACE,
 | 
						|
                    Private->Snp
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Open SNP on the child handle BY_DRIVER. It will prevent any additionally 
 | 
						|
    // layering to perform the experiment.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Private->Ip4Nic->Controller,
 | 
						|
                    &gEfiSimpleNetworkProtocolGuid,
 | 
						|
                    (VOID **) &Snp,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Private->Ip4Nic->Controller,
 | 
						|
                    EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
 | 
						|
  // real NIC handle and the virtual IPv4 NIC handle.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  ControllerHandle,
 | 
						|
                  &gEfiCallerIdGuid,
 | 
						|
                  (VOID **) &Id,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Private->Ip4Nic->Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set default configure data for Udp4Read and Ip4 instance.
 | 
						|
  //
 | 
						|
  Mode                            = Private->PxeBc.Mode;
 | 
						|
  Udp4CfgData                     = &Private->Udp4CfgData;
 | 
						|
  Ip4CfgData                      = &Private->Ip4CfgData;
 | 
						|
 | 
						|
  Udp4CfgData->AcceptBroadcast    = FALSE;
 | 
						|
  Udp4CfgData->AcceptAnyPort      = TRUE;
 | 
						|
  Udp4CfgData->AllowDuplicatePort = TRUE;
 | 
						|
  Udp4CfgData->TypeOfService      = Mode->ToS;
 | 
						|
  Udp4CfgData->TimeToLive         = Mode->TTL;
 | 
						|
  Udp4CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
 | 
						|
  Udp4CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;
 | 
						|
 | 
						|
  Ip4CfgData->AcceptIcmpErrors    = TRUE;
 | 
						|
  Ip4CfgData->DefaultProtocol     = EFI_IP_PROTO_ICMP;
 | 
						|
  Ip4CfgData->TypeOfService       = Mode->ToS;
 | 
						|
  Ip4CfgData->TimeToLive          = Mode->TTL;
 | 
						|
  Ip4CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
 | 
						|
  Ip4CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
ON_ERROR:
 | 
						|
  PxeBcDestroyIp4Children (This, Private);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Create the opened instances based on IPv6.
 | 
						|
 | 
						|
  @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
 | 
						|
  @param[in]  ControllerHandle  Handle of the child to destroy.
 | 
						|
  @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           The instances based on IPv6 were all created successfully.
 | 
						|
  @retval Others                An unexpected error occurred.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
PxeBcCreateIp6Children (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN PXEBC_PRIVATE_DATA           *Private
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  IPv6_DEVICE_PATH                Ip6Node;
 | 
						|
  EFI_UDP6_CONFIG_DATA            *Udp6CfgData;
 | 
						|
  EFI_IP6_CONFIG_DATA             *Ip6CfgData;
 | 
						|
  EFI_IP6_MODE_DATA               Ip6ModeData;
 | 
						|
  PXEBC_PRIVATE_PROTOCOL          *Id;
 | 
						|
  EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
 | 
						|
  UINTN                           Index;
 | 
						|
 | 
						|
  if (Private->Ip6Nic != NULL) {
 | 
						|
    //
 | 
						|
    // Already created before.
 | 
						|
    //
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
 | 
						|
 | 
						|
  if (Private->Ip6Nic == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Ip6Nic->Private   = Private;
 | 
						|
  Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiDhcp6ServiceBindingProtocolGuid,
 | 
						|
             &Private->Dhcp6Child
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Dhcp6Child,
 | 
						|
                  &gEfiDhcp6ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Dhcp6,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Generate a random IAID for the Dhcp6 assigned address.
 | 
						|
  //
 | 
						|
  Private->IaId = NET_RANDOM (NetRandomInitSeed ());
 | 
						|
  if (Private->Snp != NULL) {
 | 
						|
    for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
 | 
						|
      Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
 | 
						|
    }  
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiMtftp6ServiceBindingProtocolGuid,
 | 
						|
             &Private->Mtftp6Child
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Mtftp6Child,
 | 
						|
                  &gEfiMtftp6ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Mtftp6,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiUdp6ServiceBindingProtocolGuid,
 | 
						|
             &Private->Udp6ReadChild
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Udp6ReadChild,
 | 
						|
                  &gEfiUdp6ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Udp6Read,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiUdp6ServiceBindingProtocolGuid,
 | 
						|
             &Private->Udp6WriteChild
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Udp6WriteChild,
 | 
						|
                  &gEfiUdp6ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Udp6Write,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
 | 
						|
  //
 | 
						|
  Status = NetLibCreateServiceChild (
 | 
						|
             ControllerHandle,
 | 
						|
             This->DriverBindingHandle,
 | 
						|
             &gEfiIp6ServiceBindingProtocolGuid,
 | 
						|
             &Private->Ip6Child
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  Private->Ip6Child,
 | 
						|
                  &gEfiIp6ProtocolGuid,
 | 
						|
                  (VOID **) &Private->Ip6,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Get max packet size from Ip6 to calculate block size for Tftp later.
 | 
						|
  //
 | 
						|
  Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;
 | 
						|
 | 
						|
  if (Ip6ModeData.AddressList != NULL) {
 | 
						|
    FreePool (Ip6ModeData.AddressList);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Ip6ModeData.GroupTable != NULL) {
 | 
						|
    FreePool (Ip6ModeData.GroupTable);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Ip6ModeData.RouteTable != NULL) {
 | 
						|
    FreePool (Ip6ModeData.RouteTable);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Ip6ModeData.NeighborCache != NULL) {
 | 
						|
    FreePool (Ip6ModeData.NeighborCache);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Ip6ModeData.PrefixTable != NULL) {
 | 
						|
    FreePool (Ip6ModeData.PrefixTable);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Ip6ModeData.IcmpTypeList != NULL) {
 | 
						|
    FreePool (Ip6ModeData.IcmpTypeList);
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Locate Ip6->Ip6Config and store it for set IPv6 address.
 | 
						|
  //
 | 
						|
  Status = gBS->HandleProtocol (
 | 
						|
                  ControllerHandle,
 | 
						|
                  &gEfiIp6ConfigProtocolGuid,
 | 
						|
                  (VOID **) &Private->Ip6Cfg
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Create a device path node for Ipv6 virtual nic, and append it.
 | 
						|
  //
 | 
						|
  ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));
 | 
						|
  Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;
 | 
						|
  Ip6Node.Header.SubType  = MSG_IPv6_DP;
 | 
						|
  Ip6Node.PrefixLength    = IP6_PREFIX_LENGTH;
 | 
						|
 | 
						|
  SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));
 | 
						|
 | 
						|
  Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);
 | 
						|
 | 
						|
  if (Private->Ip6Nic->DevicePath == NULL) {
 | 
						|
    Status = EFI_OUT_OF_RESOURCES;
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  CopyMem (
 | 
						|
    &Private->Ip6Nic->LoadFile,
 | 
						|
    &gLoadFileProtocolTemplate,
 | 
						|
    sizeof (EFI_LOAD_FILE_PROTOCOL)
 | 
						|
    );
 | 
						|
 | 
						|
  //
 | 
						|
  // Create a new handle for IPv6 virtual nic,
 | 
						|
  // and install PxeBaseCode, LoadFile and DevicePath protocols.
 | 
						|
  //
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces (
 | 
						|
                  &Private->Ip6Nic->Controller,
 | 
						|
                  &gEfiDevicePathProtocolGuid,
 | 
						|
                  Private->Ip6Nic->DevicePath,
 | 
						|
                  &gEfiLoadFileProtocolGuid,
 | 
						|
                  &Private->Ip6Nic->LoadFile,
 | 
						|
                  &gEfiPxeBaseCodeProtocolGuid,
 | 
						|
                  &Private->PxeBc,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
  
 | 
						|
  if (Private->Snp != NULL) {
 | 
						|
    //
 | 
						|
    // Install SNP protocol on purpose is for some OS loader backward
 | 
						|
    // compatibility consideration.
 | 
						|
    //
 | 
						|
    Status = gBS->InstallProtocolInterface (
 | 
						|
                    &Private->Ip6Nic->Controller,
 | 
						|
                    &gEfiSimpleNetworkProtocolGuid,
 | 
						|
                    EFI_NATIVE_INTERFACE,
 | 
						|
                    Private->Snp
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Open SNP on the child handle BY_DRIVER. It will prevent any additionally 
 | 
						|
    // layering to perform the experiment.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    Private->Ip6Nic->Controller,
 | 
						|
                    &gEfiSimpleNetworkProtocolGuid,
 | 
						|
                    (VOID **) &Snp,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    Private->Ip6Nic->Controller,
 | 
						|
                    EFI_OPEN_PROTOCOL_BY_DRIVER
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_ERROR;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
 | 
						|
  // real NIC handle and the virtual IPv6 NIC handle.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  ControllerHandle,
 | 
						|
                  &gEfiCallerIdGuid,
 | 
						|
                  (VOID **) &Id,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  Private->Ip6Nic->Controller,
 | 
						|
                  EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Set IPv6 avaiable flag and set default configure data for
 | 
						|
  // Udp6Read and Ip6 instance.
 | 
						|
  //
 | 
						|
  Status = PxeBcCheckIpv6Support (ControllerHandle, Private, &Private->Mode.Ipv6Available);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Fail to get the data whether UNDI supports IPv6. Set default value.
 | 
						|
    //
 | 
						|
    Private->Mode.Ipv6Available   = TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  if (!Private->Mode.Ipv6Available) {
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  Udp6CfgData                     = &Private->Udp6CfgData;
 | 
						|
  Ip6CfgData                      = &Private->Ip6CfgData;
 | 
						|
 | 
						|
  Udp6CfgData->AcceptAnyPort      = TRUE;
 | 
						|
  Udp6CfgData->AllowDuplicatePort = TRUE;
 | 
						|
  Udp6CfgData->HopLimit           = PXEBC_DEFAULT_HOPLIMIT;
 | 
						|
  Udp6CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
 | 
						|
  Udp6CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;
 | 
						|
 | 
						|
  Ip6CfgData->AcceptIcmpErrors    = TRUE;
 | 
						|
  Ip6CfgData->DefaultProtocol     = IP6_ICMP;
 | 
						|
  Ip6CfgData->HopLimit            = PXEBC_DEFAULT_HOPLIMIT;
 | 
						|
  Ip6CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
 | 
						|
  Ip6CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
ON_ERROR:
 | 
						|
  PxeBcDestroyIp6Children (This, Private);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  The entry point for UefiPxeBc driver that installs the driver
 | 
						|
  binding and component name protocol on its image.
 | 
						|
 | 
						|
  @param[in]  ImageHandle          The Image handle of the driver.
 | 
						|
  @param[in]  SystemTable          The system table.
 | 
						|
 | 
						|
  @return EFI_SUCCESS
 | 
						|
  @return Others
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcDriverEntryPoint (
 | 
						|
  IN EFI_HANDLE             ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE       *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS  Status;
 | 
						|
 | 
						|
  Status = EfiLibInstallDriverBindingComponentName2 (
 | 
						|
             ImageHandle,
 | 
						|
             SystemTable,
 | 
						|
             &gPxeBcIp4DriverBinding,
 | 
						|
             ImageHandle,
 | 
						|
             &gPxeBcComponentName,
 | 
						|
             &gPxeBcComponentName2
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = EfiLibInstallDriverBindingComponentName2 (
 | 
						|
             ImageHandle,
 | 
						|
             SystemTable,
 | 
						|
             &gPxeBcIp6DriverBinding,
 | 
						|
             NULL,
 | 
						|
             &gPxeBcComponentName,
 | 
						|
             &gPxeBcComponentName2
 | 
						|
             );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    gBS->UninstallMultipleProtocolInterfaces (
 | 
						|
           ImageHandle,
 | 
						|
           &gEfiDriverBindingProtocolGuid,
 | 
						|
           &gPxeBcIp4DriverBinding,
 | 
						|
           &gEfiComponentName2ProtocolGuid,
 | 
						|
           &gPxeBcComponentName2,
 | 
						|
           &gEfiComponentNameProtocolGuid,
 | 
						|
           &gPxeBcComponentName,
 | 
						|
           NULL
 | 
						|
           );
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Test to see if this driver supports ControllerHandle. This is the worker function for
 | 
						|
  PxeBcIp4(6)DriverBindingSupported.
 | 
						|
 | 
						|
  @param[in]  This                The pointer to the driver binding protocol.
 | 
						|
  @param[in]  ControllerHandle    The handle of device to be tested.
 | 
						|
  @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
 | 
						|
                                  device to be started.
 | 
						|
  @param[in]  IpVersion           IP_VERSION_4 or IP_VERSION_6.
 | 
						|
  
 | 
						|
  @retval EFI_SUCCESS         This driver supports this device.
 | 
						|
  @retval EFI_UNSUPPORTED     This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
 | 
						|
  IN UINT8                        IpVersion
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_GUID                        *DhcpServiceBindingGuid;
 | 
						|
  EFI_GUID                        *MtftpServiceBindingGuid;
 | 
						|
  
 | 
						|
  if (IpVersion == IP_VERSION_4) {
 | 
						|
    DhcpServiceBindingGuid  = &gEfiDhcp4ServiceBindingProtocolGuid;
 | 
						|
    MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid;
 | 
						|
  } else {
 | 
						|
    DhcpServiceBindingGuid  = &gEfiDhcp6ServiceBindingProtocolGuid;
 | 
						|
    MtftpServiceBindingGuid = &gEfiMtftp6ServiceBindingProtocolGuid;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Try to open the Mtftp and Dhcp protocol to test whether IP stack is ready.
 | 
						|
  //
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                     ControllerHandle,
 | 
						|
                     DhcpServiceBindingGuid,
 | 
						|
                     NULL,
 | 
						|
                     This->DriverBindingHandle,
 | 
						|
                     ControllerHandle,
 | 
						|
                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                     );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                       ControllerHandle,
 | 
						|
                       MtftpServiceBindingGuid,
 | 
						|
                       NULL,
 | 
						|
                       This->DriverBindingHandle,
 | 
						|
                       ControllerHandle,
 | 
						|
                       EFI_OPEN_PROTOCOL_TEST_PROTOCOL
 | 
						|
                       );
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // It's unsupported case if IP stack are not ready.
 | 
						|
  //
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start this driver on ControllerHandle. This is the worker function for
 | 
						|
  PxeBcIp4(6)DriverBindingStart.
 | 
						|
 | 
						|
  @param[in]  This                 The pointer to the driver binding protocol.
 | 
						|
  @param[in]  ControllerHandle     The handle of device to be started.
 | 
						|
  @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
 | 
						|
                                   device to be started.
 | 
						|
  @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
 | 
						|
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
 | 
						|
  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
 | 
						|
  @retval other                This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
 | 
						|
  IN UINT8                        IpVersion
 | 
						|
  )
 | 
						|
{
 | 
						|
  PXEBC_PRIVATE_DATA              *Private;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  PXEBC_PRIVATE_PROTOCOL          *Id;
 | 
						|
  BOOLEAN                         FirstStart;
 | 
						|
 | 
						|
  FirstStart = FALSE;
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  ControllerHandle,
 | 
						|
                  &gEfiCallerIdGuid,
 | 
						|
                  (VOID **) &Id,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Skip the initialization if the driver has been started already.
 | 
						|
    //
 | 
						|
    Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
 | 
						|
  } else {
 | 
						|
    FirstStart = TRUE;
 | 
						|
    //
 | 
						|
    // If the driver has not been started yet, it should do initialization.
 | 
						|
    //
 | 
						|
    Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
 | 
						|
    if (Private == NULL) {
 | 
						|
      return EFI_OUT_OF_RESOURCES;
 | 
						|
    }
 | 
						|
 | 
						|
    CopyMem (
 | 
						|
      &Private->PxeBc,
 | 
						|
      &gPxeBcProtocolTemplate,
 | 
						|
      sizeof (EFI_PXE_BASE_CODE_PROTOCOL)
 | 
						|
      );
 | 
						|
 | 
						|
    Private->Signature          = PXEBC_PRIVATE_DATA_SIGNATURE;
 | 
						|
    Private->Controller         = ControllerHandle;
 | 
						|
    Private->Image              = This->ImageHandle;
 | 
						|
    Private->PxeBc.Mode         = &Private->Mode;
 | 
						|
    Private->Mode.Ipv6Supported = TRUE;
 | 
						|
    Private->Mode.AutoArp       = TRUE;
 | 
						|
    Private->Mode.TTL           = DEFAULT_TTL;
 | 
						|
    Private->Mode.ToS           = DEFAULT_ToS;
 | 
						|
 | 
						|
    //
 | 
						|
    // Open device path to prepare for appending virtual NIC node.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    ControllerHandle,
 | 
						|
                    &gEfiDevicePathProtocolGuid,
 | 
						|
                    (VOID **) &Private->DevicePath,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    ControllerHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Get the NII interface if it exists, it's not required.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    ControllerHandle,
 | 
						|
                    &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
 | 
						|
                    (VOID **) &Private->Nii,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    ControllerHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      Private->Nii = NULL;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Install PxeBaseCodePrivate protocol onto the real NIC handler.
 | 
						|
    // PxeBaseCodePrivate protocol is only used to keep the relationship between 
 | 
						|
    // NIC handle and virtual child handles.
 | 
						|
    // gEfiCallerIdGuid will be used as its protocol guid.
 | 
						|
    //
 | 
						|
    Status = gBS->InstallProtocolInterface (
 | 
						|
                    &ControllerHandle,
 | 
						|
                    &gEfiCallerIdGuid,
 | 
						|
                    EFI_NATIVE_INTERFACE,
 | 
						|
                    &Private->Id
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      goto ON_ERROR;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Try to locate SNP protocol.
 | 
						|
    //
 | 
						|
    NetLibGetSnpHandle(ControllerHandle, &Private->Snp);    
 | 
						|
  }
 | 
						|
 | 
						|
  if (IpVersion == IP_VERSION_4) {
 | 
						|
    //
 | 
						|
    // Try to create virtual NIC handle for IPv4.
 | 
						|
    //
 | 
						|
    Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Try to create virtual NIC handle for IPv6.
 | 
						|
    //
 | 
						|
    Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);
 | 
						|
  }
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
 | 
						|
    //
 | 
						|
    Status = EFI_DEVICE_ERROR;
 | 
						|
    goto ON_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
 | 
						|
ON_ERROR:
 | 
						|
  if (FirstStart) {
 | 
						|
    gBS->UninstallProtocolInterface (
 | 
						|
           ControllerHandle,
 | 
						|
           &gEfiCallerIdGuid,
 | 
						|
           &Private->Id
 | 
						|
           );
 | 
						|
  }
 | 
						|
 | 
						|
  if (IpVersion == IP_VERSION_4) {
 | 
						|
    PxeBcDestroyIp4Children (This, Private);
 | 
						|
  } else {
 | 
						|
    PxeBcDestroyIp6Children (This, Private);
 | 
						|
  }
 | 
						|
 | 
						|
  if (FirstStart && Private != NULL) {
 | 
						|
    FreePool (Private);
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/**
 | 
						|
  Stop this driver on ControllerHandle. This is the worker function for
 | 
						|
  PxeBcIp4(6)DriverBindingStop.
 | 
						|
 | 
						|
  @param[in]  This              Protocol instance pointer.
 | 
						|
  @param[in]  ControllerHandle  Handle of device to stop driver on.
 | 
						|
  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
 | 
						|
                                children is zero stop the entire bus driver.
 | 
						|
  @param[in]  ChildHandleBuffer List of Child Handles to Stop.
 | 
						|
  @param[in]  IpVersion         IP_VERSION_4 or IP_VERSION_6.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           This driver was removed ControllerHandle.
 | 
						|
  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
 | 
						|
  @retval Others                This driver was not removed from this device
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcStop (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN UINTN                        NumberOfChildren,
 | 
						|
  IN EFI_HANDLE                   *ChildHandleBuffer,
 | 
						|
  IN UINT8                        IpVersion
 | 
						|
  )
 | 
						|
{
 | 
						|
  PXEBC_PRIVATE_DATA              *Private;
 | 
						|
  PXEBC_VIRTUAL_NIC               *VirtualNic;
 | 
						|
  EFI_LOAD_FILE_PROTOCOL          *LoadFile;
 | 
						|
  EFI_STATUS                      Status;
 | 
						|
  EFI_HANDLE                      NicHandle;
 | 
						|
  PXEBC_PRIVATE_PROTOCOL          *Id;
 | 
						|
 | 
						|
  Private    = NULL;
 | 
						|
  NicHandle  = NULL;
 | 
						|
  VirtualNic = NULL;
 | 
						|
  LoadFile   = NULL;
 | 
						|
  Id         = NULL;
 | 
						|
 | 
						|
  Status = gBS->OpenProtocol (
 | 
						|
                  ControllerHandle,
 | 
						|
                  &gEfiLoadFileProtocolGuid,
 | 
						|
                  (VOID **) &LoadFile,
 | 
						|
                  This->DriverBindingHandle,
 | 
						|
                  ControllerHandle,
 | 
						|
                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Get the Nic handle by any pass-over service child handle.
 | 
						|
    //
 | 
						|
    if (IpVersion == IP_VERSION_4) {
 | 
						|
      NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);
 | 
						|
    } else {
 | 
						|
      NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);
 | 
						|
    }
 | 
						|
    if (NicHandle == NULL) {
 | 
						|
      return EFI_SUCCESS;
 | 
						|
    }
 | 
						|
 | 
						|
    //
 | 
						|
    // Try to retrieve the private data by PxeBcPrivate protocol.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    NicHandle,
 | 
						|
                    &gEfiCallerIdGuid,
 | 
						|
                    (VOID **) &Id,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    ControllerHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
    Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
 | 
						|
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // It's a virtual handle with LoadFileProtocol.
 | 
						|
    //
 | 
						|
    Status = gBS->OpenProtocol (
 | 
						|
                    ControllerHandle,
 | 
						|
                    &gEfiLoadFileProtocolGuid,
 | 
						|
                    (VOID **) &LoadFile,
 | 
						|
                    This->DriverBindingHandle,
 | 
						|
                    ControllerHandle,
 | 
						|
                    EFI_OPEN_PROTOCOL_GET_PROTOCOL
 | 
						|
                    );
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);
 | 
						|
    Private    = VirtualNic->Private;
 | 
						|
    NicHandle  = Private->Controller;
 | 
						|
  }
 | 
						|
 | 
						|
  //
 | 
						|
  // Stop functionality of PXE Base Code protocol
 | 
						|
  //
 | 
						|
  Status = Private->PxeBc.Stop (&Private->PxeBc);
 | 
						|
  if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
 | 
						|
  if (Private->Ip4Nic != NULL && IpVersion == IP_VERSION_4) {
 | 
						|
    PxeBcDestroyIp4Children (This, Private);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Ip6Nic != NULL && IpVersion == IP_VERSION_6) {
 | 
						|
    PxeBcDestroyIp6Children (This, Private);
 | 
						|
  }
 | 
						|
 | 
						|
  if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {
 | 
						|
    gBS->UninstallProtocolInterface (
 | 
						|
           NicHandle,
 | 
						|
           &gEfiCallerIdGuid,
 | 
						|
           &Private->Id
 | 
						|
           );
 | 
						|
    FreePool (Private);
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Test to see if this driver supports ControllerHandle. This service
 | 
						|
  is called by the EFI boot service ConnectController(). In
 | 
						|
  order to make drivers as small as possible, there are a few calling
 | 
						|
  restrictions for this service. ConnectController() must
 | 
						|
  follow these calling restrictions. If any other agent wishes to call
 | 
						|
  Supported() it must also follow these calling restrictions.
 | 
						|
 | 
						|
  @param[in]  This                The pointer to the driver binding protocol.
 | 
						|
  @param[in]  ControllerHandle    The handle of device to be tested.
 | 
						|
  @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
 | 
						|
                                  device to be started.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         This driver supports this device.
 | 
						|
  @retval EFI_UNSUPPORTED     This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcIp4DriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  return PxeBcSupported (
 | 
						|
           This,
 | 
						|
           ControllerHandle,
 | 
						|
           RemainingDevicePath,
 | 
						|
           IP_VERSION_4
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start this driver on ControllerHandle. This service is called by the
 | 
						|
  EFI boot service ConnectController(). In order to make
 | 
						|
  drivers as small as possible, there are a few calling restrictions for
 | 
						|
  this service. ConnectController() must follow these
 | 
						|
  calling restrictions. If any other agent wishes to call Start() it
 | 
						|
  must also follow these calling restrictions.
 | 
						|
 | 
						|
  @param[in]  This                 The pointer to the driver binding protocol.
 | 
						|
  @param[in]  ControllerHandle     The handle of device to be started.
 | 
						|
  @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
 | 
						|
                                   device to be started.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
 | 
						|
  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
 | 
						|
  @retval other                This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcIp4DriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  return PxeBcStart (
 | 
						|
           This,
 | 
						|
           ControllerHandle,
 | 
						|
           RemainingDevicePath,
 | 
						|
           IP_VERSION_4
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stop this driver on ControllerHandle. This service is called by the
 | 
						|
  EFI boot service DisconnectController(). In order to
 | 
						|
  make drivers as small as possible, there are a few calling
 | 
						|
  restrictions for this service. DisconnectController()
 | 
						|
  must follow these calling restrictions. If any other agent wishes
 | 
						|
  to call Stop() it must also follow these calling restrictions.
 | 
						|
 | 
						|
  @param[in]  This              Protocol instance pointer.
 | 
						|
  @param[in]  ControllerHandle  Handle of device to stop driver on
 | 
						|
  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
 | 
						|
                                children is zero stop the entire bus driver.
 | 
						|
  @param[in]  ChildHandleBuffer List of Child Handles to Stop.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           This driver is removed ControllerHandle
 | 
						|
  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
 | 
						|
  @retval Others                This driver was not removed from this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcIp4DriverBindingStop (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN UINTN                        NumberOfChildren,
 | 
						|
  IN EFI_HANDLE                   *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  return PxeBcStop (
 | 
						|
           This,
 | 
						|
           ControllerHandle,
 | 
						|
           NumberOfChildren,
 | 
						|
           ChildHandleBuffer,
 | 
						|
           IP_VERSION_4
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Test to see if this driver supports ControllerHandle. This service
 | 
						|
  is called by the EFI boot service ConnectController(). In
 | 
						|
  order to make drivers as small as possible, there are a few calling
 | 
						|
  restrictions for this service. ConnectController() must
 | 
						|
  follow these calling restrictions. If any other agent wishes to call
 | 
						|
  Supported() it must also follow these calling restrictions.
 | 
						|
 | 
						|
  @param[in]  This                The pointer to the driver binding protocol.
 | 
						|
  @param[in]  ControllerHandle    The handle of device to be tested.
 | 
						|
  @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
 | 
						|
                                  device to be started.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS         This driver supports this device.
 | 
						|
  @retval EFI_UNSUPPORTED     This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcIp6DriverBindingSupported (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  return PxeBcSupported (
 | 
						|
           This,
 | 
						|
           ControllerHandle,
 | 
						|
           RemainingDevicePath,
 | 
						|
           IP_VERSION_6
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Start this driver on ControllerHandle. This service is called by the
 | 
						|
  EFI boot service ConnectController(). In order to make
 | 
						|
  drivers as small as possible, there are a few calling restrictions for
 | 
						|
  this service. ConnectController() must follow these
 | 
						|
  calling restrictions. If any other agent wishes to call Start() it
 | 
						|
  must also follow these calling restrictions.
 | 
						|
 | 
						|
  @param[in]  This                 The pointer to the driver binding protocol.
 | 
						|
  @param[in]  ControllerHandle     The handle of device to be started.
 | 
						|
  @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
 | 
						|
                                   device to be started.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
 | 
						|
  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
 | 
						|
  @retval other                This driver does not support this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcIp6DriverBindingStart (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
 | 
						|
  )
 | 
						|
{
 | 
						|
  return PxeBcStart (
 | 
						|
           This,
 | 
						|
           ControllerHandle,
 | 
						|
           RemainingDevicePath,
 | 
						|
           IP_VERSION_6
 | 
						|
           );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Stop this driver on ControllerHandle. This service is called by the
 | 
						|
  EFI boot service DisconnectController(). In order to
 | 
						|
  make drivers as small as possible, there are a few calling
 | 
						|
  restrictions for this service. DisconnectController()
 | 
						|
  must follow these calling restrictions. If any other agent wishes
 | 
						|
  to call Stop() it must also follow these calling restrictions.
 | 
						|
 | 
						|
  @param[in]  This              Protocol instance pointer.
 | 
						|
  @param[in]  ControllerHandle  Handle of device to stop driver on
 | 
						|
  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
 | 
						|
                                children is zero stop the entire bus driver.
 | 
						|
  @param[in]  ChildHandleBuffer List of Child Handles to Stop.
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           This driver is removed ControllerHandle
 | 
						|
  @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
 | 
						|
  @retval Others                This driver was not removed from this device.
 | 
						|
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
PxeBcIp6DriverBindingStop (
 | 
						|
  IN EFI_DRIVER_BINDING_PROTOCOL  *This,
 | 
						|
  IN EFI_HANDLE                   ControllerHandle,
 | 
						|
  IN UINTN                        NumberOfChildren,
 | 
						|
  IN EFI_HANDLE                   *ChildHandleBuffer
 | 
						|
  )
 | 
						|
{
 | 
						|
  return PxeBcStop (
 | 
						|
           This,
 | 
						|
           ControllerHandle,
 | 
						|
           NumberOfChildren,
 | 
						|
           ChildHandleBuffer,
 | 
						|
           IP_VERSION_6
 | 
						|
           );
 | 
						|
}
 |