Home | History | Annotate | Download | only in UefiPxeBcDxe
      1 /** @file
      2   Driver Binding functions implementationfor for UefiPxeBc Driver.
      3 
      4   (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
      5   Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
      6 
      7   This program and the accompanying materials
      8   are licensed and made available under the terms and conditions of the BSD License
      9   which accompanies this distribution.  The full text of the license may be found at
     10   http://opensource.org/licenses/bsd-license.php.
     11 
     12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     14 
     15 **/
     16 
     17 #include "PxeBcImpl.h"
     18 
     19 
     20 EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp4DriverBinding = {
     21   PxeBcIp4DriverBindingSupported,
     22   PxeBcIp4DriverBindingStart,
     23   PxeBcIp4DriverBindingStop,
     24   0xa,
     25   NULL,
     26   NULL
     27 };
     28 
     29 EFI_DRIVER_BINDING_PROTOCOL gPxeBcIp6DriverBinding = {
     30   PxeBcIp6DriverBindingSupported,
     31   PxeBcIp6DriverBindingStart,
     32   PxeBcIp6DriverBindingStop,
     33   0xa,
     34   NULL,
     35   NULL
     36 };
     37 
     38 /**
     39   Get the Nic handle using any child handle in the IPv4 stack.
     40 
     41   @param[in]  ControllerHandle    Pointer to child handle over IPv4.
     42 
     43   @return NicHandle               The pointer to the Nic handle.
     44 
     45 **/
     46 EFI_HANDLE
     47 PxeBcGetNicByIp4Children (
     48   IN EFI_HANDLE                 ControllerHandle
     49   )
     50 {
     51   EFI_HANDLE                    NicHandle;
     52 
     53   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
     54   if (NicHandle == NULL) {
     55     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
     56     if (NicHandle == NULL) {
     57       NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
     58       if (NicHandle == NULL) {
     59         NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
     60         if (NicHandle == NULL) {
     61           NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
     62           if (NicHandle == NULL) {
     63             return NULL;
     64           }
     65         }
     66       }
     67     }
     68   }
     69 
     70   return NicHandle;
     71 }
     72 
     73 
     74 /**
     75   Get the Nic handle using any child handle in the IPv6 stack.
     76 
     77   @param[in]  ControllerHandle    Pointer to child handle over IPv6.
     78 
     79   @return NicHandle               The pointer to the Nic handle.
     80 
     81 **/
     82 EFI_HANDLE
     83 PxeBcGetNicByIp6Children (
     84   IN EFI_HANDLE                  ControllerHandle
     85   )
     86 {
     87   EFI_HANDLE                     NicHandle;
     88 
     89   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp6ProtocolGuid);
     90   if (NicHandle == NULL) {
     91     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
     92     if (NicHandle == NULL) {
     93       NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);
     94       if (NicHandle == NULL) {
     95         NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp6ProtocolGuid);
     96         if (NicHandle == NULL) {
     97           return NULL;
     98         }
     99       }
    100     }
    101   }
    102 
    103   return NicHandle;
    104 }
    105 
    106 
    107 /**
    108   Destroy the opened instances based on IPv4.
    109 
    110   @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
    111   @param[in]  Private           Pointer to PXEBC_PRIVATE_DATA.
    112 
    113 **/
    114 VOID
    115 PxeBcDestroyIp4Children (
    116   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    117   IN PXEBC_PRIVATE_DATA           *Private
    118   )
    119 {
    120   ASSERT(Private != NULL);
    121 
    122   if (Private->ArpChild != NULL) {
    123     //
    124     // Close Arp for PxeBc->Arp and destroy the instance.
    125     //
    126     gBS->CloseProtocol (
    127            Private->ArpChild,
    128            &gEfiArpProtocolGuid,
    129            This->DriverBindingHandle,
    130            Private->Controller
    131            );
    132 
    133     NetLibDestroyServiceChild (
    134       Private->Controller,
    135       This->DriverBindingHandle,
    136       &gEfiArpServiceBindingProtocolGuid,
    137       Private->ArpChild
    138       );
    139   }
    140 
    141   if (Private->Ip4Child != NULL) {
    142     //
    143     // Close Ip4 for background ICMP error message and destroy the instance.
    144     //
    145     gBS->CloseProtocol (
    146            Private->Ip4Child,
    147            &gEfiIp4ProtocolGuid,
    148            This->DriverBindingHandle,
    149            Private->Controller
    150            );
    151 
    152     NetLibDestroyServiceChild (
    153       Private->Controller,
    154       This->DriverBindingHandle,
    155       &gEfiIp4ServiceBindingProtocolGuid,
    156       Private->Ip4Child
    157       );
    158   }
    159 
    160   if (Private->Udp4WriteChild != NULL) {
    161     //
    162     // Close Udp4 for PxeBc->UdpWrite and destroy the instance.
    163     //
    164     gBS->CloseProtocol (
    165            Private->Udp4WriteChild,
    166            &gEfiUdp4ProtocolGuid,
    167            This->DriverBindingHandle,
    168            Private->Controller
    169            );
    170 
    171     NetLibDestroyServiceChild (
    172       Private->Controller,
    173       This->DriverBindingHandle,
    174       &gEfiUdp4ServiceBindingProtocolGuid,
    175       Private->Udp4WriteChild
    176       );
    177   }
    178 
    179   if (Private->Udp4ReadChild != NULL) {
    180     //
    181     // Close Udp4 for PxeBc->UdpRead and destroy the instance.
    182     //
    183     gBS->CloseProtocol (
    184           Private->Udp4ReadChild,
    185           &gEfiUdp4ProtocolGuid,
    186           This->DriverBindingHandle,
    187           Private->Controller
    188           );
    189 
    190     NetLibDestroyServiceChild (
    191       Private->Controller,
    192       This->DriverBindingHandle,
    193       &gEfiUdp4ServiceBindingProtocolGuid,
    194       Private->Udp4ReadChild
    195       );
    196   }
    197 
    198   if (Private->Mtftp4Child != NULL) {
    199     //
    200     // Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance.
    201     //
    202     gBS->CloseProtocol (
    203           Private->Mtftp4Child,
    204           &gEfiMtftp4ProtocolGuid,
    205           This->DriverBindingHandle,
    206           Private->Controller
    207           );
    208 
    209     NetLibDestroyServiceChild (
    210       Private->Controller,
    211       This->DriverBindingHandle,
    212       &gEfiMtftp4ServiceBindingProtocolGuid,
    213       Private->Mtftp4Child
    214       );
    215   }
    216 
    217   if (Private->Dhcp4Child != NULL) {
    218     //
    219     // Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance.
    220     //
    221     gBS->CloseProtocol (
    222           Private->Dhcp4Child,
    223           &gEfiDhcp4ProtocolGuid,
    224           This->DriverBindingHandle,
    225           Private->Controller
    226           );
    227 
    228     NetLibDestroyServiceChild (
    229       Private->Controller,
    230       This->DriverBindingHandle,
    231       &gEfiDhcp4ServiceBindingProtocolGuid,
    232       Private->Dhcp4Child
    233       );
    234   }
    235 
    236   if (Private->Ip4Nic != NULL) {
    237     //
    238     // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
    239     //
    240     gBS->CloseProtocol (
    241            Private->Controller,
    242            &gEfiCallerIdGuid,
    243            This->DriverBindingHandle,
    244            Private->Ip4Nic->Controller
    245            );
    246 
    247     gBS->UninstallMultipleProtocolInterfaces (
    248            Private->Ip4Nic->Controller,
    249            &gEfiDevicePathProtocolGuid,
    250            Private->Ip4Nic->DevicePath,
    251            &gEfiLoadFileProtocolGuid,
    252            &Private->Ip4Nic->LoadFile,
    253            &gEfiPxeBaseCodeProtocolGuid,
    254            &Private->PxeBc,
    255            NULL
    256            );
    257 
    258     if (Private->Snp != NULL) {
    259       //
    260       // Close SNP from the child virtual handle
    261       //
    262       gBS->CloseProtocol (
    263              Private->Ip4Nic->Controller,
    264              &gEfiSimpleNetworkProtocolGuid,
    265              This->DriverBindingHandle,
    266              Private->Ip4Nic->Controller
    267              );
    268 
    269       gBS->UninstallProtocolInterface (
    270              Private->Ip4Nic->Controller,
    271              &gEfiSimpleNetworkProtocolGuid,
    272              Private->Snp
    273              );
    274     }
    275     FreePool (Private->Ip4Nic);
    276   }
    277 
    278   Private->ArpChild         = NULL;
    279   Private->Ip4Child         = NULL;
    280   Private->Udp4WriteChild   = NULL;
    281   Private->Udp4ReadChild    = NULL;
    282   Private->Mtftp4Child      = NULL;
    283   Private->Dhcp4Child       = NULL;
    284   Private->Ip4Nic           = NULL;
    285 }
    286 
    287 
    288 /**
    289   Destroy the opened instances based on IPv6.
    290 
    291   @param[in]  This              Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
    292   @param[in]  Private           Pointer to PXEBC_PRIVATE_DATA.
    293 
    294 **/
    295 VOID
    296 PxeBcDestroyIp6Children (
    297   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    298   IN PXEBC_PRIVATE_DATA           *Private
    299   )
    300 {
    301   ASSERT(Private != NULL);
    302 
    303   if (Private->Ip6Child != NULL) {
    304     //
    305     // Close Ip6 for Ip6->Ip6Config and destroy the instance.
    306     //
    307     gBS->CloseProtocol (
    308           Private->Ip6Child,
    309           &gEfiIp6ProtocolGuid,
    310           This->DriverBindingHandle,
    311           Private->Controller
    312           );
    313 
    314     NetLibDestroyServiceChild (
    315       Private->Controller,
    316       This->DriverBindingHandle,
    317       &gEfiIp6ServiceBindingProtocolGuid,
    318       Private->Ip6Child
    319       );
    320   }
    321 
    322   if (Private->Udp6WriteChild != NULL) {
    323     //
    324     // Close Udp6 for PxeBc->UdpWrite and destroy the instance.
    325     //
    326     gBS->CloseProtocol (
    327            Private->Udp6WriteChild,
    328            &gEfiUdp6ProtocolGuid,
    329            This->DriverBindingHandle,
    330            Private->Controller
    331            );
    332     NetLibDestroyServiceChild (
    333       Private->Controller,
    334       This->DriverBindingHandle,
    335       &gEfiUdp6ServiceBindingProtocolGuid,
    336       Private->Udp6WriteChild
    337       );
    338   }
    339 
    340   if (Private->Udp6ReadChild != NULL) {
    341     //
    342     // Close Udp6 for PxeBc->UdpRead and destroy the instance.
    343     //
    344     gBS->CloseProtocol (
    345           Private->Udp6ReadChild,
    346           &gEfiUdp6ProtocolGuid,
    347           This->DriverBindingHandle,
    348           Private->Controller
    349           );
    350     NetLibDestroyServiceChild (
    351       Private->Controller,
    352       This->DriverBindingHandle,
    353       &gEfiUdp6ServiceBindingProtocolGuid,
    354       Private->Udp6ReadChild
    355       );
    356   }
    357 
    358   if (Private->Mtftp6Child != NULL) {
    359     //
    360     // Close Mtftp6 for PxeBc->Mtftp and destroy the instance.
    361     //
    362     gBS->CloseProtocol (
    363           Private->Mtftp6Child,
    364           &gEfiMtftp6ProtocolGuid,
    365           This->DriverBindingHandle,
    366           Private->Controller
    367           );
    368 
    369     NetLibDestroyServiceChild (
    370       Private->Controller,
    371       This->DriverBindingHandle,
    372       &gEfiMtftp6ServiceBindingProtocolGuid,
    373       Private->Mtftp6Child
    374       );
    375   }
    376 
    377   if (Private->Dhcp6Child != NULL) {
    378     //
    379     // Close Dhcp6 for PxeBc->Dhcp and destroy the instance.
    380     //
    381     gBS->CloseProtocol (
    382           Private->Dhcp6Child,
    383           &gEfiDhcp6ProtocolGuid,
    384           This->DriverBindingHandle,
    385           Private->Controller
    386           );
    387 
    388     NetLibDestroyServiceChild (
    389       Private->Controller,
    390       This->DriverBindingHandle,
    391       &gEfiDhcp6ServiceBindingProtocolGuid,
    392       Private->Dhcp6Child
    393       );
    394   }
    395 
    396   if (Private->Ip6Nic != NULL) {
    397     //
    398     // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle.
    399     //
    400     gBS->CloseProtocol (
    401            Private->Controller,
    402            &gEfiCallerIdGuid,
    403            This->DriverBindingHandle,
    404            Private->Ip6Nic->Controller
    405            );
    406 
    407     gBS->UninstallMultipleProtocolInterfaces (
    408            Private->Ip6Nic->Controller,
    409            &gEfiDevicePathProtocolGuid,
    410            Private->Ip6Nic->DevicePath,
    411            &gEfiLoadFileProtocolGuid,
    412            &Private->Ip6Nic->LoadFile,
    413            &gEfiPxeBaseCodeProtocolGuid,
    414            &Private->PxeBc,
    415            NULL
    416            );
    417     if (Private->Snp != NULL) {
    418       //
    419       // Close SNP from the child virtual handle
    420       //
    421       gBS->CloseProtocol (
    422              Private->Ip6Nic->Controller,
    423              &gEfiSimpleNetworkProtocolGuid,
    424              This->DriverBindingHandle,
    425              Private->Ip6Nic->Controller
    426              );
    427       gBS->UninstallProtocolInterface (
    428              Private->Ip6Nic->Controller,
    429              &gEfiSimpleNetworkProtocolGuid,
    430              Private->Snp
    431              );
    432     }
    433     FreePool (Private->Ip6Nic);
    434   }
    435 
    436   Private->Ip6Child           = NULL;
    437   Private->Udp6WriteChild     = NULL;
    438   Private->Udp6ReadChild      = NULL;
    439   Private->Mtftp6Child        = NULL;
    440   Private->Dhcp6Child         = NULL;
    441   Private->Ip6Nic             = NULL;
    442   Private->Mode.Ipv6Available = FALSE;
    443 }
    444 
    445 /**
    446   Check whether UNDI protocol supports IPv6.
    447 
    448   @param[in]   ControllerHandle  Controller handle.
    449   @param[in]   Private           Pointer to PXEBC_PRIVATE_DATA.
    450   @param[out]  Ipv6Support       TRUE if UNDI supports IPv6.
    451 
    452   @retval EFI_SUCCESS            Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.
    453   @retval EFI_NOT_FOUND          Don't know whether UNDI supports IPv6 since NII or AIP is not available.
    454 
    455 **/
    456 EFI_STATUS
    457 PxeBcCheckIpv6Support (
    458   IN  EFI_HANDLE                   ControllerHandle,
    459   IN  PXEBC_PRIVATE_DATA           *Private,
    460   OUT BOOLEAN                      *Ipv6Support
    461   )
    462 {
    463   EFI_HANDLE                       Handle;
    464   EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;
    465   EFI_STATUS                       Status;
    466   EFI_GUID                         *InfoTypesBuffer;
    467   UINTN                            InfoTypeBufferCount;
    468   UINTN                            TypeIndex;
    469   BOOLEAN                          Supported;
    470   VOID                             *InfoBlock;
    471   UINTN                            InfoBlockSize;
    472 
    473   ASSERT (Private != NULL && Ipv6Support != NULL);
    474 
    475   //
    476   // Check whether the UNDI supports IPv6 by NII protocol.
    477   //
    478   if (Private->Nii != NULL) {
    479     *Ipv6Support = Private->Nii->Ipv6Supported;
    480     return EFI_SUCCESS;
    481   }
    482 
    483   //
    484   // Check whether the UNDI supports IPv6 by AIP protocol.
    485   //
    486 
    487   //
    488   // Get the NIC handle by SNP protocol.
    489   //
    490   Handle = NetLibGetSnpHandle (ControllerHandle, NULL);
    491   if (Handle == NULL) {
    492     return EFI_NOT_FOUND;
    493   }
    494 
    495   Aip    = NULL;
    496   Status = gBS->HandleProtocol (
    497                   Handle,
    498                   &gEfiAdapterInformationProtocolGuid,
    499                   (VOID *) &Aip
    500                   );
    501   if (EFI_ERROR (Status) || Aip == NULL) {
    502     return EFI_NOT_FOUND;
    503   }
    504 
    505   InfoTypesBuffer     = NULL;
    506   InfoTypeBufferCount = 0;
    507   Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);
    508   if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {
    509     FreePool (InfoTypesBuffer);
    510     return EFI_NOT_FOUND;
    511   }
    512 
    513   Supported = FALSE;
    514   for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {
    515     if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {
    516       Supported = TRUE;
    517       break;
    518     }
    519   }
    520 
    521   FreePool (InfoTypesBuffer);
    522   if (!Supported) {
    523     return EFI_NOT_FOUND;
    524   }
    525 
    526   //
    527   // We now have adapter information block.
    528   //
    529   InfoBlock     = NULL;
    530   InfoBlockSize = 0;
    531   Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);
    532   if (EFI_ERROR (Status) || InfoBlock == NULL) {
    533     FreePool (InfoBlock);
    534     return EFI_NOT_FOUND;
    535   }
    536 
    537   *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support;
    538   FreePool (InfoBlock);
    539   return EFI_SUCCESS;
    540 
    541 }
    542 
    543 /**
    544   Create the opened instances based on IPv4.
    545 
    546   @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
    547   @param[in]  ControllerHandle  Handle of the child to destroy.
    548   @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.
    549 
    550   @retval EFI_SUCCESS           The instances based on IPv4 were all created successfully.
    551   @retval Others                An unexpected error occurred.
    552 
    553 **/
    554 EFI_STATUS
    555 PxeBcCreateIp4Children (
    556   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    557   IN EFI_HANDLE                   ControllerHandle,
    558   IN PXEBC_PRIVATE_DATA           *Private
    559   )
    560 {
    561   EFI_STATUS                      Status;
    562   IPv4_DEVICE_PATH                Ip4Node;
    563   EFI_PXE_BASE_CODE_MODE          *Mode;
    564   EFI_UDP4_CONFIG_DATA            *Udp4CfgData;
    565   EFI_IP4_CONFIG_DATA             *Ip4CfgData;
    566   EFI_IP4_MODE_DATA               Ip4ModeData;
    567   PXEBC_PRIVATE_PROTOCOL          *Id;
    568   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
    569 
    570   if (Private->Ip4Nic != NULL) {
    571     //
    572     // Already created before.
    573     //
    574     return EFI_SUCCESS;
    575   }
    576 
    577   //
    578   // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.
    579   //
    580   Status = NetLibCreateServiceChild (
    581              ControllerHandle,
    582              This->DriverBindingHandle,
    583              &gEfiDhcp4ServiceBindingProtocolGuid,
    584              &Private->Dhcp4Child
    585              );
    586   if (EFI_ERROR (Status)) {
    587     goto ON_ERROR;
    588   }
    589 
    590   Status = gBS->OpenProtocol (
    591                   Private->Dhcp4Child,
    592                   &gEfiDhcp4ProtocolGuid,
    593                   (VOID **) &Private->Dhcp4,
    594                   This->DriverBindingHandle,
    595                   ControllerHandle,
    596                   EFI_OPEN_PROTOCOL_BY_DRIVER
    597                   );
    598   if (EFI_ERROR (Status)) {
    599     goto ON_ERROR;
    600   }
    601 
    602   //
    603   // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.
    604   //
    605   Status = NetLibCreateServiceChild (
    606              ControllerHandle,
    607              This->DriverBindingHandle,
    608              &gEfiMtftp4ServiceBindingProtocolGuid,
    609              &Private->Mtftp4Child
    610              );
    611   if (EFI_ERROR (Status)) {
    612     goto ON_ERROR;
    613   }
    614 
    615   Status = gBS->OpenProtocol (
    616                   Private->Mtftp4Child,
    617                   &gEfiMtftp4ProtocolGuid,
    618                   (VOID **) &Private->Mtftp4,
    619                   This->DriverBindingHandle,
    620                   ControllerHandle,
    621                   EFI_OPEN_PROTOCOL_BY_DRIVER
    622                   );
    623   if (EFI_ERROR (Status)) {
    624     goto ON_ERROR;
    625   }
    626 
    627   //
    628   // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.
    629   //
    630   Status = NetLibCreateServiceChild (
    631              ControllerHandle,
    632              This->DriverBindingHandle,
    633              &gEfiUdp4ServiceBindingProtocolGuid,
    634              &Private->Udp4ReadChild
    635              );
    636   if (EFI_ERROR (Status)) {
    637     goto ON_ERROR;
    638   }
    639 
    640   Status = gBS->OpenProtocol (
    641                   Private->Udp4ReadChild,
    642                   &gEfiUdp4ProtocolGuid,
    643                   (VOID **) &Private->Udp4Read,
    644                   This->DriverBindingHandle,
    645                   ControllerHandle,
    646                   EFI_OPEN_PROTOCOL_BY_DRIVER
    647                   );
    648   if (EFI_ERROR (Status)) {
    649     goto ON_ERROR;
    650   }
    651 
    652   //
    653   // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.
    654   //
    655   Status = NetLibCreateServiceChild (
    656              ControllerHandle,
    657              This->DriverBindingHandle,
    658              &gEfiUdp4ServiceBindingProtocolGuid,
    659              &Private->Udp4WriteChild
    660              );
    661   if (EFI_ERROR (Status)) {
    662     goto ON_ERROR;
    663   }
    664 
    665   Status = gBS->OpenProtocol (
    666                   Private->Udp4WriteChild,
    667                   &gEfiUdp4ProtocolGuid,
    668                   (VOID **) &Private->Udp4Write,
    669                   This->DriverBindingHandle,
    670                   ControllerHandle,
    671                   EFI_OPEN_PROTOCOL_BY_DRIVER
    672                   );
    673   if (EFI_ERROR (Status)) {
    674     goto ON_ERROR;
    675   }
    676 
    677   //
    678   // Create Arp child and open Arp protocol for PxeBc->Arp.
    679   //
    680   Status = NetLibCreateServiceChild (
    681              ControllerHandle,
    682              This->DriverBindingHandle,
    683              &gEfiArpServiceBindingProtocolGuid,
    684              &Private->ArpChild
    685              );
    686   if (EFI_ERROR (Status)) {
    687     goto ON_ERROR;
    688   }
    689 
    690   Status = gBS->OpenProtocol (
    691                   Private->ArpChild,
    692                   &gEfiArpProtocolGuid,
    693                   (VOID **) &Private->Arp,
    694                   This->DriverBindingHandle,
    695                   ControllerHandle,
    696                   EFI_OPEN_PROTOCOL_BY_DRIVER
    697                   );
    698   if (EFI_ERROR (Status)) {
    699     goto ON_ERROR;
    700   }
    701 
    702   //
    703   // Create Ip4 child and open Ip4 protocol for background ICMP packets.
    704   //
    705   Status = NetLibCreateServiceChild (
    706              ControllerHandle,
    707              This->DriverBindingHandle,
    708              &gEfiIp4ServiceBindingProtocolGuid,
    709              &Private->Ip4Child
    710              );
    711   if (EFI_ERROR (Status)) {
    712     goto ON_ERROR;
    713   }
    714 
    715   Status = gBS->OpenProtocol (
    716                   Private->Ip4Child,
    717                   &gEfiIp4ProtocolGuid,
    718                   (VOID **) &Private->Ip4,
    719                   This->DriverBindingHandle,
    720                   ControllerHandle,
    721                   EFI_OPEN_PROTOCOL_BY_DRIVER
    722                   );
    723   if (EFI_ERROR (Status)) {
    724     goto ON_ERROR;
    725   }
    726 
    727   //
    728   // Get max packet size from Ip4 to calculate block size for Tftp later.
    729   //
    730   Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
    731   if (EFI_ERROR (Status)) {
    732     goto ON_ERROR;
    733   }
    734 
    735   Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;
    736 
    737   Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
    738   if (Private->Ip4Nic == NULL) {
    739     return EFI_OUT_OF_RESOURCES;
    740   }
    741 
    742   Private->Ip4Nic->Private   = Private;
    743   Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
    744 
    745    //
    746   // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.
    747   //
    748   Status = gBS->HandleProtocol (
    749                   ControllerHandle,
    750                   &gEfiIp4Config2ProtocolGuid,
    751                   (VOID **) &Private->Ip4Config2
    752                   );
    753   if (EFI_ERROR (Status)) {
    754     goto ON_ERROR;
    755   }
    756 
    757   //
    758   // Create a device path node for Ipv4 virtual nic, and append it.
    759   //
    760   ZeroMem (&Ip4Node, sizeof (IPv4_DEVICE_PATH));
    761   Ip4Node.Header.Type     = MESSAGING_DEVICE_PATH;
    762   Ip4Node.Header.SubType  = MSG_IPv4_DP;
    763   Ip4Node.StaticIpAddress = FALSE;
    764 
    765   SetDevicePathNodeLength (&Ip4Node.Header, sizeof (Ip4Node));
    766 
    767   Private->Ip4Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip4Node.Header);
    768 
    769   if (Private->Ip4Nic->DevicePath == NULL) {
    770     Status = EFI_OUT_OF_RESOURCES;
    771     goto ON_ERROR;
    772   }
    773 
    774   CopyMem (
    775     &Private->Ip4Nic->LoadFile,
    776     &gLoadFileProtocolTemplate,
    777     sizeof (EFI_LOAD_FILE_PROTOCOL)
    778     );
    779 
    780   //
    781   // Create a new handle for IPv4 virtual nic,
    782   // and install PxeBaseCode, LoadFile and DevicePath protocols.
    783   //
    784   Status = gBS->InstallMultipleProtocolInterfaces (
    785                   &Private->Ip4Nic->Controller,
    786                   &gEfiDevicePathProtocolGuid,
    787                   Private->Ip4Nic->DevicePath,
    788                   &gEfiLoadFileProtocolGuid,
    789                   &Private->Ip4Nic->LoadFile,
    790                   &gEfiPxeBaseCodeProtocolGuid,
    791                   &Private->PxeBc,
    792                   NULL
    793                   );
    794   if (EFI_ERROR (Status)) {
    795     goto ON_ERROR;
    796   }
    797 
    798   if (Private->Snp != NULL) {
    799     //
    800     // Install SNP protocol on purpose is for some OS loader backward
    801     // compatibility consideration.
    802     //
    803     Status = gBS->InstallProtocolInterface (
    804                     &Private->Ip4Nic->Controller,
    805                     &gEfiSimpleNetworkProtocolGuid,
    806                     EFI_NATIVE_INTERFACE,
    807                     Private->Snp
    808                     );
    809     if (EFI_ERROR (Status)) {
    810       goto ON_ERROR;
    811     }
    812 
    813     //
    814     // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
    815     // layering to perform the experiment.
    816     //
    817     Status = gBS->OpenProtocol (
    818                     Private->Ip4Nic->Controller,
    819                     &gEfiSimpleNetworkProtocolGuid,
    820                     (VOID **) &Snp,
    821                     This->DriverBindingHandle,
    822                     Private->Ip4Nic->Controller,
    823                     EFI_OPEN_PROTOCOL_BY_DRIVER
    824                     );
    825     if (EFI_ERROR (Status)) {
    826       goto ON_ERROR;
    827     }
    828   }
    829 
    830   //
    831   // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
    832   // real NIC handle and the virtual IPv4 NIC handle.
    833   //
    834   Status = gBS->OpenProtocol (
    835                   ControllerHandle,
    836                   &gEfiCallerIdGuid,
    837                   (VOID **) &Id,
    838                   This->DriverBindingHandle,
    839                   Private->Ip4Nic->Controller,
    840                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    841                   );
    842   if (EFI_ERROR (Status)) {
    843     goto ON_ERROR;
    844   }
    845 
    846   //
    847   // Set default configure data for Udp4Read and Ip4 instance.
    848   //
    849   Mode                            = Private->PxeBc.Mode;
    850   Udp4CfgData                     = &Private->Udp4CfgData;
    851   Ip4CfgData                      = &Private->Ip4CfgData;
    852 
    853   Udp4CfgData->AcceptBroadcast    = FALSE;
    854   Udp4CfgData->AcceptAnyPort      = TRUE;
    855   Udp4CfgData->AllowDuplicatePort = TRUE;
    856   Udp4CfgData->TypeOfService      = Mode->ToS;
    857   Udp4CfgData->TimeToLive         = Mode->TTL;
    858   Udp4CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
    859   Udp4CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;
    860 
    861   Ip4CfgData->AcceptIcmpErrors    = TRUE;
    862   Ip4CfgData->DefaultProtocol     = EFI_IP_PROTO_ICMP;
    863   Ip4CfgData->TypeOfService       = Mode->ToS;
    864   Ip4CfgData->TimeToLive          = Mode->TTL;
    865   Ip4CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
    866   Ip4CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;
    867 
    868   return EFI_SUCCESS;
    869 
    870 ON_ERROR:
    871   PxeBcDestroyIp4Children (This, Private);
    872   return Status;
    873 }
    874 
    875 
    876 /**
    877   Create the opened instances based on IPv6.
    878 
    879   @param[in]  This              Pointer to EFI_DRIVER_BINDING_PROTOCOL.
    880   @param[in]  ControllerHandle  Handle of the child to destroy.
    881   @param[in]  Private Handle    Pointer to PXEBC_PRIVATE_DATA.
    882 
    883   @retval EFI_SUCCESS           The instances based on IPv6 were all created successfully.
    884   @retval Others                An unexpected error occurred.
    885 
    886 **/
    887 EFI_STATUS
    888 PxeBcCreateIp6Children (
    889   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    890   IN EFI_HANDLE                   ControllerHandle,
    891   IN PXEBC_PRIVATE_DATA           *Private
    892   )
    893 {
    894   EFI_STATUS                      Status;
    895   IPv6_DEVICE_PATH                Ip6Node;
    896   EFI_UDP6_CONFIG_DATA            *Udp6CfgData;
    897   EFI_IP6_CONFIG_DATA             *Ip6CfgData;
    898   EFI_IP6_MODE_DATA               Ip6ModeData;
    899   PXEBC_PRIVATE_PROTOCOL          *Id;
    900   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;
    901   UINTN                           Index;
    902 
    903   if (Private->Ip6Nic != NULL) {
    904     //
    905     // Already created before.
    906     //
    907     return EFI_SUCCESS;
    908   }
    909 
    910   Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));
    911 
    912   if (Private->Ip6Nic == NULL) {
    913     return EFI_OUT_OF_RESOURCES;
    914   }
    915 
    916   Private->Ip6Nic->Private   = Private;
    917   Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;
    918 
    919   //
    920   // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.
    921   //
    922   Status = NetLibCreateServiceChild (
    923              ControllerHandle,
    924              This->DriverBindingHandle,
    925              &gEfiDhcp6ServiceBindingProtocolGuid,
    926              &Private->Dhcp6Child
    927              );
    928   if (EFI_ERROR (Status)) {
    929     goto ON_ERROR;
    930   }
    931 
    932   Status = gBS->OpenProtocol (
    933                   Private->Dhcp6Child,
    934                   &gEfiDhcp6ProtocolGuid,
    935                   (VOID **) &Private->Dhcp6,
    936                   This->DriverBindingHandle,
    937                   ControllerHandle,
    938                   EFI_OPEN_PROTOCOL_BY_DRIVER
    939                   );
    940   if (EFI_ERROR (Status)) {
    941     goto ON_ERROR;
    942   }
    943 
    944   //
    945   // Generate a random IAID for the Dhcp6 assigned address.
    946   //
    947   Private->IaId = NET_RANDOM (NetRandomInitSeed ());
    948   if (Private->Snp != NULL) {
    949     for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {
    950       Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));
    951     }
    952   }
    953 
    954   //
    955   // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.
    956   //
    957   Status = NetLibCreateServiceChild (
    958              ControllerHandle,
    959              This->DriverBindingHandle,
    960              &gEfiMtftp6ServiceBindingProtocolGuid,
    961              &Private->Mtftp6Child
    962              );
    963   if (EFI_ERROR (Status)) {
    964     goto ON_ERROR;
    965   }
    966 
    967   Status = gBS->OpenProtocol (
    968                   Private->Mtftp6Child,
    969                   &gEfiMtftp6ProtocolGuid,
    970                   (VOID **) &Private->Mtftp6,
    971                   This->DriverBindingHandle,
    972                   ControllerHandle,
    973                   EFI_OPEN_PROTOCOL_BY_DRIVER
    974                   );
    975   if (EFI_ERROR (Status)) {
    976     goto ON_ERROR;
    977   }
    978 
    979   //
    980   // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.
    981   //
    982   Status = NetLibCreateServiceChild (
    983              ControllerHandle,
    984              This->DriverBindingHandle,
    985              &gEfiUdp6ServiceBindingProtocolGuid,
    986              &Private->Udp6ReadChild
    987              );
    988   if (EFI_ERROR (Status)) {
    989     goto ON_ERROR;
    990   }
    991 
    992   Status = gBS->OpenProtocol (
    993                   Private->Udp6ReadChild,
    994                   &gEfiUdp6ProtocolGuid,
    995                   (VOID **) &Private->Udp6Read,
    996                   This->DriverBindingHandle,
    997                   ControllerHandle,
    998                   EFI_OPEN_PROTOCOL_BY_DRIVER
    999                   );
   1000   if (EFI_ERROR (Status)) {
   1001     goto ON_ERROR;
   1002   }
   1003 
   1004   //
   1005   // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.
   1006   //
   1007   Status = NetLibCreateServiceChild (
   1008              ControllerHandle,
   1009              This->DriverBindingHandle,
   1010              &gEfiUdp6ServiceBindingProtocolGuid,
   1011              &Private->Udp6WriteChild
   1012              );
   1013   if (EFI_ERROR (Status)) {
   1014     goto ON_ERROR;
   1015   }
   1016 
   1017   Status = gBS->OpenProtocol (
   1018                   Private->Udp6WriteChild,
   1019                   &gEfiUdp6ProtocolGuid,
   1020                   (VOID **) &Private->Udp6Write,
   1021                   This->DriverBindingHandle,
   1022                   ControllerHandle,
   1023                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1024                   );
   1025   if (EFI_ERROR (Status)) {
   1026     goto ON_ERROR;
   1027   }
   1028 
   1029   //
   1030   // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.
   1031   //
   1032   Status = NetLibCreateServiceChild (
   1033              ControllerHandle,
   1034              This->DriverBindingHandle,
   1035              &gEfiIp6ServiceBindingProtocolGuid,
   1036              &Private->Ip6Child
   1037              );
   1038   if (EFI_ERROR (Status)) {
   1039     goto ON_ERROR;
   1040   }
   1041 
   1042   Status = gBS->OpenProtocol (
   1043                   Private->Ip6Child,
   1044                   &gEfiIp6ProtocolGuid,
   1045                   (VOID **) &Private->Ip6,
   1046                   This->DriverBindingHandle,
   1047                   ControllerHandle,
   1048                   EFI_OPEN_PROTOCOL_BY_DRIVER
   1049                   );
   1050   if (EFI_ERROR (Status)) {
   1051     goto ON_ERROR;
   1052   }
   1053 
   1054   //
   1055   // Get max packet size from Ip6 to calculate block size for Tftp later.
   1056   //
   1057   Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL);
   1058   if (EFI_ERROR (Status)) {
   1059     goto ON_ERROR;
   1060   }
   1061 
   1062   Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;
   1063 
   1064   if (Ip6ModeData.AddressList != NULL) {
   1065     FreePool (Ip6ModeData.AddressList);
   1066   }
   1067 
   1068   if (Ip6ModeData.GroupTable != NULL) {
   1069     FreePool (Ip6ModeData.GroupTable);
   1070   }
   1071 
   1072   if (Ip6ModeData.RouteTable != NULL) {
   1073     FreePool (Ip6ModeData.RouteTable);
   1074   }
   1075 
   1076   if (Ip6ModeData.NeighborCache != NULL) {
   1077     FreePool (Ip6ModeData.NeighborCache);
   1078   }
   1079 
   1080   if (Ip6ModeData.PrefixTable != NULL) {
   1081     FreePool (Ip6ModeData.PrefixTable);
   1082   }
   1083 
   1084   if (Ip6ModeData.IcmpTypeList != NULL) {
   1085     FreePool (Ip6ModeData.IcmpTypeList);
   1086   }
   1087 
   1088   //
   1089   // Locate Ip6->Ip6Config and store it for set IPv6 address.
   1090   //
   1091   Status = gBS->HandleProtocol (
   1092                   ControllerHandle,
   1093                   &gEfiIp6ConfigProtocolGuid,
   1094                   (VOID **) &Private->Ip6Cfg
   1095                   );
   1096   if (EFI_ERROR (Status)) {
   1097     goto ON_ERROR;
   1098   }
   1099 
   1100   //
   1101   // Create a device path node for Ipv6 virtual nic, and append it.
   1102   //
   1103   ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));
   1104   Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;
   1105   Ip6Node.Header.SubType  = MSG_IPv6_DP;
   1106   Ip6Node.PrefixLength    = IP6_PREFIX_LENGTH;
   1107 
   1108   SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));
   1109 
   1110   Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);
   1111 
   1112   if (Private->Ip6Nic->DevicePath == NULL) {
   1113     Status = EFI_OUT_OF_RESOURCES;
   1114     goto ON_ERROR;
   1115   }
   1116 
   1117   CopyMem (
   1118     &Private->Ip6Nic->LoadFile,
   1119     &gLoadFileProtocolTemplate,
   1120     sizeof (EFI_LOAD_FILE_PROTOCOL)
   1121     );
   1122 
   1123   //
   1124   // Create a new handle for IPv6 virtual nic,
   1125   // and install PxeBaseCode, LoadFile and DevicePath protocols.
   1126   //
   1127   Status = gBS->InstallMultipleProtocolInterfaces (
   1128                   &Private->Ip6Nic->Controller,
   1129                   &gEfiDevicePathProtocolGuid,
   1130                   Private->Ip6Nic->DevicePath,
   1131                   &gEfiLoadFileProtocolGuid,
   1132                   &Private->Ip6Nic->LoadFile,
   1133                   &gEfiPxeBaseCodeProtocolGuid,
   1134                   &Private->PxeBc,
   1135                   NULL
   1136                   );
   1137   if (EFI_ERROR (Status)) {
   1138     goto ON_ERROR;
   1139   }
   1140 
   1141   if (Private->Snp != NULL) {
   1142     //
   1143     // Install SNP protocol on purpose is for some OS loader backward
   1144     // compatibility consideration.
   1145     //
   1146     Status = gBS->InstallProtocolInterface (
   1147                     &Private->Ip6Nic->Controller,
   1148                     &gEfiSimpleNetworkProtocolGuid,
   1149                     EFI_NATIVE_INTERFACE,
   1150                     Private->Snp
   1151                     );
   1152     if (EFI_ERROR (Status)) {
   1153       goto ON_ERROR;
   1154     }
   1155 
   1156     //
   1157     // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
   1158     // layering to perform the experiment.
   1159     //
   1160     Status = gBS->OpenProtocol (
   1161                     Private->Ip6Nic->Controller,
   1162                     &gEfiSimpleNetworkProtocolGuid,
   1163                     (VOID **) &Snp,
   1164                     This->DriverBindingHandle,
   1165                     Private->Ip6Nic->Controller,
   1166                     EFI_OPEN_PROTOCOL_BY_DRIVER
   1167                     );
   1168     if (EFI_ERROR (Status)) {
   1169       goto ON_ERROR;
   1170     }
   1171   }
   1172 
   1173   //
   1174   // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
   1175   // real NIC handle and the virtual IPv6 NIC handle.
   1176   //
   1177   Status = gBS->OpenProtocol (
   1178                   ControllerHandle,
   1179                   &gEfiCallerIdGuid,
   1180                   (VOID **) &Id,
   1181                   This->DriverBindingHandle,
   1182                   Private->Ip6Nic->Controller,
   1183                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
   1184                   );
   1185   if (EFI_ERROR (Status)) {
   1186     goto ON_ERROR;
   1187   }
   1188 
   1189   //
   1190   // Set IPv6 avaiable flag and set default configure data for
   1191   // Udp6Read and Ip6 instance.
   1192   //
   1193   Status = PxeBcCheckIpv6Support (ControllerHandle, Private, &Private->Mode.Ipv6Available);
   1194   if (EFI_ERROR (Status)) {
   1195     //
   1196     // Fail to get the data whether UNDI supports IPv6. Set default value.
   1197     //
   1198     Private->Mode.Ipv6Available   = TRUE;
   1199   }
   1200 
   1201   if (!Private->Mode.Ipv6Available) {
   1202     goto ON_ERROR;
   1203   }
   1204 
   1205   Udp6CfgData                     = &Private->Udp6CfgData;
   1206   Ip6CfgData                      = &Private->Ip6CfgData;
   1207 
   1208   Udp6CfgData->AcceptAnyPort      = TRUE;
   1209   Udp6CfgData->AllowDuplicatePort = TRUE;
   1210   Udp6CfgData->HopLimit           = PXEBC_DEFAULT_HOPLIMIT;
   1211   Udp6CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
   1212   Udp6CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;
   1213 
   1214   Ip6CfgData->AcceptIcmpErrors    = TRUE;
   1215   Ip6CfgData->DefaultProtocol     = IP6_ICMP;
   1216   Ip6CfgData->HopLimit            = PXEBC_DEFAULT_HOPLIMIT;
   1217   Ip6CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
   1218   Ip6CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;
   1219 
   1220   return EFI_SUCCESS;
   1221 
   1222 ON_ERROR:
   1223   PxeBcDestroyIp6Children (This, Private);
   1224   return Status;
   1225 }
   1226 
   1227 
   1228 /**
   1229   The entry point for UefiPxeBc driver that installs the driver
   1230   binding and component name protocol on its image.
   1231 
   1232   @param[in]  ImageHandle          The Image handle of the driver.
   1233   @param[in]  SystemTable          The system table.
   1234 
   1235   @return EFI_SUCCESS
   1236   @return Others
   1237 
   1238 **/
   1239 EFI_STATUS
   1240 EFIAPI
   1241 PxeBcDriverEntryPoint (
   1242   IN EFI_HANDLE             ImageHandle,
   1243   IN EFI_SYSTEM_TABLE       *SystemTable
   1244   )
   1245 {
   1246   EFI_STATUS  Status;
   1247 
   1248   Status = EfiLibInstallDriverBindingComponentName2 (
   1249              ImageHandle,
   1250              SystemTable,
   1251              &gPxeBcIp4DriverBinding,
   1252              ImageHandle,
   1253              &gPxeBcComponentName,
   1254              &gPxeBcComponentName2
   1255              );
   1256   if (EFI_ERROR (Status)) {
   1257     return Status;
   1258   }
   1259 
   1260   Status = EfiLibInstallDriverBindingComponentName2 (
   1261              ImageHandle,
   1262              SystemTable,
   1263              &gPxeBcIp6DriverBinding,
   1264              NULL,
   1265              &gPxeBcComponentName,
   1266              &gPxeBcComponentName2
   1267              );
   1268   if (EFI_ERROR (Status)) {
   1269     gBS->UninstallMultipleProtocolInterfaces (
   1270            ImageHandle,
   1271            &gEfiDriverBindingProtocolGuid,
   1272            &gPxeBcIp4DriverBinding,
   1273            &gEfiComponentName2ProtocolGuid,
   1274            &gPxeBcComponentName2,
   1275            &gEfiComponentNameProtocolGuid,
   1276            &gPxeBcComponentName,
   1277            NULL
   1278            );
   1279   }
   1280 
   1281   return Status;
   1282 }
   1283 
   1284 /**
   1285   Test to see if this driver supports ControllerHandle. This is the worker function for
   1286   PxeBcIp4(6)DriverBindingSupported.
   1287 
   1288   @param[in]  This                The pointer to the driver binding protocol.
   1289   @param[in]  ControllerHandle    The handle of device to be tested.
   1290   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
   1291                                   device to be started.
   1292   @param[in]  IpVersion           IP_VERSION_4 or IP_VERSION_6.
   1293 
   1294   @retval EFI_SUCCESS         This driver supports this device.
   1295   @retval EFI_UNSUPPORTED     This driver does not support this device.
   1296 
   1297 **/
   1298 EFI_STATUS
   1299 EFIAPI
   1300 PxeBcSupported (
   1301   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1302   IN EFI_HANDLE                   ControllerHandle,
   1303   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
   1304   IN UINT8                        IpVersion
   1305   )
   1306 {
   1307   EFI_STATUS                      Status;
   1308   EFI_GUID                        *DhcpServiceBindingGuid;
   1309   EFI_GUID                        *MtftpServiceBindingGuid;
   1310 
   1311   if (IpVersion == IP_VERSION_4) {
   1312     DhcpServiceBindingGuid  = &gEfiDhcp4ServiceBindingProtocolGuid;
   1313     MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid;
   1314   } else {
   1315     DhcpServiceBindingGuid  = &gEfiDhcp6ServiceBindingProtocolGuid;
   1316     MtftpServiceBindingGuid = &gEfiMtftp6ServiceBindingProtocolGuid;
   1317   }
   1318 
   1319   //
   1320   // Try to open the Mtftp and Dhcp protocol to test whether IP stack is ready.
   1321   //
   1322   Status = gBS->OpenProtocol (
   1323                      ControllerHandle,
   1324                      DhcpServiceBindingGuid,
   1325                      NULL,
   1326                      This->DriverBindingHandle,
   1327                      ControllerHandle,
   1328                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL
   1329                      );
   1330   if (!EFI_ERROR (Status)) {
   1331     Status = gBS->OpenProtocol (
   1332                        ControllerHandle,
   1333                        MtftpServiceBindingGuid,
   1334                        NULL,
   1335                        This->DriverBindingHandle,
   1336                        ControllerHandle,
   1337                        EFI_OPEN_PROTOCOL_TEST_PROTOCOL
   1338                        );
   1339   }
   1340 
   1341   //
   1342   // It's unsupported case if IP stack are not ready.
   1343   //
   1344   if (EFI_ERROR (Status)) {
   1345     return EFI_UNSUPPORTED;
   1346   }
   1347 
   1348   return EFI_SUCCESS;
   1349 }
   1350 
   1351 /**
   1352   Start this driver on ControllerHandle. This is the worker function for
   1353   PxeBcIp4(6)DriverBindingStart.
   1354 
   1355   @param[in]  This                 The pointer to the driver binding protocol.
   1356   @param[in]  ControllerHandle     The handle of device to be started.
   1357   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
   1358                                    device to be started.
   1359   @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
   1360 
   1361 
   1362   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
   1363   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
   1364   @retval other                This driver does not support this device.
   1365 
   1366 **/
   1367 EFI_STATUS
   1368 EFIAPI
   1369 PxeBcStart (
   1370   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1371   IN EFI_HANDLE                   ControllerHandle,
   1372   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
   1373   IN UINT8                        IpVersion
   1374   )
   1375 {
   1376   PXEBC_PRIVATE_DATA              *Private;
   1377   EFI_STATUS                      Status;
   1378   PXEBC_PRIVATE_PROTOCOL          *Id;
   1379   BOOLEAN                         FirstStart;
   1380 
   1381   FirstStart = FALSE;
   1382   Status = gBS->OpenProtocol (
   1383                   ControllerHandle,
   1384                   &gEfiCallerIdGuid,
   1385                   (VOID **) &Id,
   1386                   This->DriverBindingHandle,
   1387                   ControllerHandle,
   1388                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1389                   );
   1390   if (!EFI_ERROR (Status)) {
   1391     //
   1392     // Skip the initialization if the driver has been started already.
   1393     //
   1394     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
   1395   } else {
   1396     FirstStart = TRUE;
   1397     //
   1398     // If the driver has not been started yet, it should do initialization.
   1399     //
   1400     Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
   1401     if (Private == NULL) {
   1402       return EFI_OUT_OF_RESOURCES;
   1403     }
   1404 
   1405     CopyMem (
   1406       &Private->PxeBc,
   1407       &gPxeBcProtocolTemplate,
   1408       sizeof (EFI_PXE_BASE_CODE_PROTOCOL)
   1409       );
   1410 
   1411     Private->Signature          = PXEBC_PRIVATE_DATA_SIGNATURE;
   1412     Private->Controller         = ControllerHandle;
   1413     Private->Image              = This->ImageHandle;
   1414     Private->PxeBc.Mode         = &Private->Mode;
   1415     Private->Mode.Ipv6Supported = TRUE;
   1416     Private->Mode.AutoArp       = TRUE;
   1417     Private->Mode.TTL           = DEFAULT_TTL;
   1418     Private->Mode.ToS           = DEFAULT_ToS;
   1419 
   1420     //
   1421     // Open device path to prepare for appending virtual NIC node.
   1422     //
   1423     Status = gBS->OpenProtocol (
   1424                     ControllerHandle,
   1425                     &gEfiDevicePathProtocolGuid,
   1426                     (VOID **) &Private->DevicePath,
   1427                     This->DriverBindingHandle,
   1428                     ControllerHandle,
   1429                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1430                     );
   1431 
   1432     if (EFI_ERROR (Status)) {
   1433       goto ON_ERROR;
   1434     }
   1435 
   1436     //
   1437     // Get the NII interface if it exists, it's not required.
   1438     //
   1439     Status = gBS->OpenProtocol (
   1440                     ControllerHandle,
   1441                     &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
   1442                     (VOID **) &Private->Nii,
   1443                     This->DriverBindingHandle,
   1444                     ControllerHandle,
   1445                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1446                     );
   1447     if (EFI_ERROR (Status)) {
   1448       Private->Nii = NULL;
   1449     }
   1450 
   1451     //
   1452     // Install PxeBaseCodePrivate protocol onto the real NIC handler.
   1453     // PxeBaseCodePrivate protocol is only used to keep the relationship between
   1454     // NIC handle and virtual child handles.
   1455     // gEfiCallerIdGuid will be used as its protocol guid.
   1456     //
   1457     Status = gBS->InstallProtocolInterface (
   1458                     &ControllerHandle,
   1459                     &gEfiCallerIdGuid,
   1460                     EFI_NATIVE_INTERFACE,
   1461                     &Private->Id
   1462                     );
   1463     if (EFI_ERROR (Status)) {
   1464       goto ON_ERROR;
   1465     }
   1466 
   1467     //
   1468     // Try to locate SNP protocol.
   1469     //
   1470     NetLibGetSnpHandle(ControllerHandle, &Private->Snp);
   1471   }
   1472 
   1473   if (IpVersion == IP_VERSION_4) {
   1474     //
   1475     // Try to create virtual NIC handle for IPv4.
   1476     //
   1477     Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);
   1478   } else {
   1479     //
   1480     // Try to create virtual NIC handle for IPv6.
   1481     //
   1482     Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);
   1483   }
   1484   if (EFI_ERROR (Status)) {
   1485     //
   1486     // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
   1487     //
   1488     Status = EFI_DEVICE_ERROR;
   1489     goto ON_ERROR;
   1490   }
   1491 
   1492   return EFI_SUCCESS;
   1493 
   1494 ON_ERROR:
   1495   if (FirstStart) {
   1496     gBS->UninstallProtocolInterface (
   1497            ControllerHandle,
   1498            &gEfiCallerIdGuid,
   1499            &Private->Id
   1500            );
   1501   }
   1502 
   1503   if (IpVersion == IP_VERSION_4) {
   1504     PxeBcDestroyIp4Children (This, Private);
   1505   } else {
   1506     PxeBcDestroyIp6Children (This, Private);
   1507   }
   1508 
   1509   if (FirstStart && Private != NULL) {
   1510     FreePool (Private);
   1511   }
   1512 
   1513   return Status;
   1514 }
   1515 
   1516 
   1517 /**
   1518   Stop this driver on ControllerHandle. This is the worker function for
   1519   PxeBcIp4(6)DriverBindingStop.
   1520 
   1521   @param[in]  This              Protocol instance pointer.
   1522   @param[in]  ControllerHandle  Handle of device to stop driver on.
   1523   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
   1524                                 children is zero stop the entire bus driver.
   1525   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
   1526   @param[in]  IpVersion         IP_VERSION_4 or IP_VERSION_6.
   1527 
   1528   @retval EFI_SUCCESS           This driver was removed ControllerHandle.
   1529   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
   1530   @retval Others                This driver was not removed from this device
   1531 
   1532 **/
   1533 EFI_STATUS
   1534 EFIAPI
   1535 PxeBcStop (
   1536   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1537   IN EFI_HANDLE                   ControllerHandle,
   1538   IN UINTN                        NumberOfChildren,
   1539   IN EFI_HANDLE                   *ChildHandleBuffer,
   1540   IN UINT8                        IpVersion
   1541   )
   1542 {
   1543   PXEBC_PRIVATE_DATA              *Private;
   1544   PXEBC_VIRTUAL_NIC               *VirtualNic;
   1545   EFI_LOAD_FILE_PROTOCOL          *LoadFile;
   1546   EFI_STATUS                      Status;
   1547   EFI_HANDLE                      NicHandle;
   1548   PXEBC_PRIVATE_PROTOCOL          *Id;
   1549 
   1550   Private    = NULL;
   1551   NicHandle  = NULL;
   1552   VirtualNic = NULL;
   1553   LoadFile   = NULL;
   1554   Id         = NULL;
   1555 
   1556   Status = gBS->OpenProtocol (
   1557                   ControllerHandle,
   1558                   &gEfiLoadFileProtocolGuid,
   1559                   (VOID **) &LoadFile,
   1560                   This->DriverBindingHandle,
   1561                   ControllerHandle,
   1562                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1563                   );
   1564   if (EFI_ERROR (Status)) {
   1565     //
   1566     // Get the Nic handle by any pass-over service child handle.
   1567     //
   1568     if (IpVersion == IP_VERSION_4) {
   1569       NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);
   1570     } else {
   1571       NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);
   1572     }
   1573     if (NicHandle == NULL) {
   1574       return EFI_SUCCESS;
   1575     }
   1576 
   1577     //
   1578     // Try to retrieve the private data by PxeBcPrivate protocol.
   1579     //
   1580     Status = gBS->OpenProtocol (
   1581                     NicHandle,
   1582                     &gEfiCallerIdGuid,
   1583                     (VOID **) &Id,
   1584                     This->DriverBindingHandle,
   1585                     ControllerHandle,
   1586                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1587                     );
   1588     if (EFI_ERROR (Status)) {
   1589       return Status;
   1590     }
   1591     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
   1592 
   1593   } else {
   1594     //
   1595     // It's a virtual handle with LoadFileProtocol.
   1596     //
   1597     Status = gBS->OpenProtocol (
   1598                     ControllerHandle,
   1599                     &gEfiLoadFileProtocolGuid,
   1600                     (VOID **) &LoadFile,
   1601                     This->DriverBindingHandle,
   1602                     ControllerHandle,
   1603                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1604                     );
   1605     if (EFI_ERROR (Status)) {
   1606       return Status;
   1607     }
   1608 
   1609     VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);
   1610     Private    = VirtualNic->Private;
   1611     NicHandle  = Private->Controller;
   1612   }
   1613 
   1614   //
   1615   // Stop functionality of PXE Base Code protocol
   1616   //
   1617   Status = Private->PxeBc.Stop (&Private->PxeBc);
   1618   if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
   1619     return Status;
   1620   }
   1621 
   1622 
   1623   if (Private->Ip4Nic != NULL && IpVersion == IP_VERSION_4) {
   1624     PxeBcDestroyIp4Children (This, Private);
   1625   }
   1626 
   1627   if (Private->Ip6Nic != NULL && IpVersion == IP_VERSION_6) {
   1628     PxeBcDestroyIp6Children (This, Private);
   1629   }
   1630 
   1631   if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {
   1632     gBS->UninstallProtocolInterface (
   1633            NicHandle,
   1634            &gEfiCallerIdGuid,
   1635            &Private->Id
   1636            );
   1637     FreePool (Private);
   1638   }
   1639 
   1640   return EFI_SUCCESS;
   1641 }
   1642 
   1643 /**
   1644   Test to see if this driver supports ControllerHandle. This service
   1645   is called by the EFI boot service ConnectController(). In
   1646   order to make drivers as small as possible, there are a few calling
   1647   restrictions for this service. ConnectController() must
   1648   follow these calling restrictions. If any other agent wishes to call
   1649   Supported() it must also follow these calling restrictions.
   1650 
   1651   @param[in]  This                The pointer to the driver binding protocol.
   1652   @param[in]  ControllerHandle    The handle of device to be tested.
   1653   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
   1654                                   device to be started.
   1655 
   1656   @retval EFI_SUCCESS         This driver supports this device.
   1657   @retval EFI_UNSUPPORTED     This driver does not support this device.
   1658 
   1659 **/
   1660 EFI_STATUS
   1661 EFIAPI
   1662 PxeBcIp4DriverBindingSupported (
   1663   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1664   IN EFI_HANDLE                   ControllerHandle,
   1665   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1666   )
   1667 {
   1668   return PxeBcSupported (
   1669            This,
   1670            ControllerHandle,
   1671            RemainingDevicePath,
   1672            IP_VERSION_4
   1673            );
   1674 }
   1675 
   1676 /**
   1677   Start this driver on ControllerHandle. This service is called by the
   1678   EFI boot service ConnectController(). In order to make
   1679   drivers as small as possible, there are a few calling restrictions for
   1680   this service. ConnectController() must follow these
   1681   calling restrictions. If any other agent wishes to call Start() it
   1682   must also follow these calling restrictions.
   1683 
   1684   @param[in]  This                 The pointer to the driver binding protocol.
   1685   @param[in]  ControllerHandle     The handle of device to be started.
   1686   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
   1687                                    device to be started.
   1688 
   1689   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
   1690   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
   1691   @retval other                This driver does not support this device.
   1692 
   1693 **/
   1694 EFI_STATUS
   1695 EFIAPI
   1696 PxeBcIp4DriverBindingStart (
   1697   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1698   IN EFI_HANDLE                   ControllerHandle,
   1699   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1700   )
   1701 {
   1702   return PxeBcStart (
   1703            This,
   1704            ControllerHandle,
   1705            RemainingDevicePath,
   1706            IP_VERSION_4
   1707            );
   1708 }
   1709 
   1710 /**
   1711   Stop this driver on ControllerHandle. This service is called by the
   1712   EFI boot service DisconnectController(). In order to
   1713   make drivers as small as possible, there are a few calling
   1714   restrictions for this service. DisconnectController()
   1715   must follow these calling restrictions. If any other agent wishes
   1716   to call Stop() it must also follow these calling restrictions.
   1717 
   1718   @param[in]  This              Protocol instance pointer.
   1719   @param[in]  ControllerHandle  Handle of device to stop driver on
   1720   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
   1721                                 children is zero stop the entire bus driver.
   1722   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
   1723 
   1724   @retval EFI_SUCCESS           This driver is removed ControllerHandle
   1725   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
   1726   @retval Others                This driver was not removed from this device.
   1727 
   1728 **/
   1729 EFI_STATUS
   1730 EFIAPI
   1731 PxeBcIp4DriverBindingStop (
   1732   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1733   IN EFI_HANDLE                   ControllerHandle,
   1734   IN UINTN                        NumberOfChildren,
   1735   IN EFI_HANDLE                   *ChildHandleBuffer
   1736   )
   1737 {
   1738   return PxeBcStop (
   1739            This,
   1740            ControllerHandle,
   1741            NumberOfChildren,
   1742            ChildHandleBuffer,
   1743            IP_VERSION_4
   1744            );
   1745 }
   1746 
   1747 /**
   1748   Test to see if this driver supports ControllerHandle. This service
   1749   is called by the EFI boot service ConnectController(). In
   1750   order to make drivers as small as possible, there are a few calling
   1751   restrictions for this service. ConnectController() must
   1752   follow these calling restrictions. If any other agent wishes to call
   1753   Supported() it must also follow these calling restrictions.
   1754 
   1755   @param[in]  This                The pointer to the driver binding protocol.
   1756   @param[in]  ControllerHandle    The handle of device to be tested.
   1757   @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
   1758                                   device to be started.
   1759 
   1760   @retval EFI_SUCCESS         This driver supports this device.
   1761   @retval EFI_UNSUPPORTED     This driver does not support this device.
   1762 
   1763 **/
   1764 EFI_STATUS
   1765 EFIAPI
   1766 PxeBcIp6DriverBindingSupported (
   1767   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1768   IN EFI_HANDLE                   ControllerHandle,
   1769   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1770   )
   1771 {
   1772   return PxeBcSupported (
   1773            This,
   1774            ControllerHandle,
   1775            RemainingDevicePath,
   1776            IP_VERSION_6
   1777            );
   1778 }
   1779 
   1780 /**
   1781   Start this driver on ControllerHandle. This service is called by the
   1782   EFI boot service ConnectController(). In order to make
   1783   drivers as small as possible, there are a few calling restrictions for
   1784   this service. ConnectController() must follow these
   1785   calling restrictions. If any other agent wishes to call Start() it
   1786   must also follow these calling restrictions.
   1787 
   1788   @param[in]  This                 The pointer to the driver binding protocol.
   1789   @param[in]  ControllerHandle     The handle of device to be started.
   1790   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
   1791                                    device to be started.
   1792 
   1793   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
   1794   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
   1795   @retval other                This driver does not support this device.
   1796 
   1797 **/
   1798 EFI_STATUS
   1799 EFIAPI
   1800 PxeBcIp6DriverBindingStart (
   1801   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1802   IN EFI_HANDLE                   ControllerHandle,
   1803   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1804   )
   1805 {
   1806   return PxeBcStart (
   1807            This,
   1808            ControllerHandle,
   1809            RemainingDevicePath,
   1810            IP_VERSION_6
   1811            );
   1812 }
   1813 
   1814 /**
   1815   Stop this driver on ControllerHandle. This service is called by the
   1816   EFI boot service DisconnectController(). In order to
   1817   make drivers as small as possible, there are a few calling
   1818   restrictions for this service. DisconnectController()
   1819   must follow these calling restrictions. If any other agent wishes
   1820   to call Stop() it must also follow these calling restrictions.
   1821 
   1822   @param[in]  This              Protocol instance pointer.
   1823   @param[in]  ControllerHandle  Handle of device to stop driver on
   1824   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
   1825                                 children is zero stop the entire bus driver.
   1826   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
   1827 
   1828   @retval EFI_SUCCESS           This driver is removed ControllerHandle
   1829   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
   1830   @retval Others                This driver was not removed from this device.
   1831 
   1832 **/
   1833 EFI_STATUS
   1834 EFIAPI
   1835 PxeBcIp6DriverBindingStop (
   1836   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1837   IN EFI_HANDLE                   ControllerHandle,
   1838   IN UINTN                        NumberOfChildren,
   1839   IN EFI_HANDLE                   *ChildHandleBuffer
   1840   )
   1841 {
   1842   return PxeBcStop (
   1843            This,
   1844            ControllerHandle,
   1845            NumberOfChildren,
   1846            ChildHandleBuffer,
   1847            IP_VERSION_6
   1848            );
   1849 }
   1850