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 - 2015, 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   //
   1065   // Locate Ip6->Ip6Config and store it for set IPv6 address.
   1066   //
   1067   Status = gBS->HandleProtocol (
   1068                   ControllerHandle,
   1069                   &gEfiIp6ConfigProtocolGuid,
   1070                   (VOID **) &Private->Ip6Cfg
   1071                   );
   1072   if (EFI_ERROR (Status)) {
   1073     goto ON_ERROR;
   1074   }
   1075 
   1076   //
   1077   // Create a device path node for Ipv6 virtual nic, and append it.
   1078   //
   1079   ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));
   1080   Ip6Node.Header.Type     = MESSAGING_DEVICE_PATH;
   1081   Ip6Node.Header.SubType  = MSG_IPv6_DP;
   1082   Ip6Node.PrefixLength    = IP6_PREFIX_LENGTH;
   1083 
   1084   SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));
   1085 
   1086   Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);
   1087 
   1088   if (Private->Ip6Nic->DevicePath == NULL) {
   1089     Status = EFI_OUT_OF_RESOURCES;
   1090     goto ON_ERROR;
   1091   }
   1092 
   1093   CopyMem (
   1094     &Private->Ip6Nic->LoadFile,
   1095     &gLoadFileProtocolTemplate,
   1096     sizeof (EFI_LOAD_FILE_PROTOCOL)
   1097     );
   1098 
   1099   //
   1100   // Create a new handle for IPv6 virtual nic,
   1101   // and install PxeBaseCode, LoadFile and DevicePath protocols.
   1102   //
   1103   Status = gBS->InstallMultipleProtocolInterfaces (
   1104                   &Private->Ip6Nic->Controller,
   1105                   &gEfiDevicePathProtocolGuid,
   1106                   Private->Ip6Nic->DevicePath,
   1107                   &gEfiLoadFileProtocolGuid,
   1108                   &Private->Ip6Nic->LoadFile,
   1109                   &gEfiPxeBaseCodeProtocolGuid,
   1110                   &Private->PxeBc,
   1111                   NULL
   1112                   );
   1113   if (EFI_ERROR (Status)) {
   1114     goto ON_ERROR;
   1115   }
   1116 
   1117   if (Private->Snp != NULL) {
   1118     //
   1119     // Install SNP protocol on purpose is for some OS loader backward
   1120     // compatibility consideration.
   1121     //
   1122     Status = gBS->InstallProtocolInterface (
   1123                     &Private->Ip6Nic->Controller,
   1124                     &gEfiSimpleNetworkProtocolGuid,
   1125                     EFI_NATIVE_INTERFACE,
   1126                     Private->Snp
   1127                     );
   1128     if (EFI_ERROR (Status)) {
   1129       goto ON_ERROR;
   1130     }
   1131 
   1132     //
   1133     // Open SNP on the child handle BY_DRIVER. It will prevent any additionally
   1134     // layering to perform the experiment.
   1135     //
   1136     Status = gBS->OpenProtocol (
   1137                     Private->Ip6Nic->Controller,
   1138                     &gEfiSimpleNetworkProtocolGuid,
   1139                     (VOID **) &Snp,
   1140                     This->DriverBindingHandle,
   1141                     Private->Ip6Nic->Controller,
   1142                     EFI_OPEN_PROTOCOL_BY_DRIVER
   1143                     );
   1144     if (EFI_ERROR (Status)) {
   1145       goto ON_ERROR;
   1146     }
   1147   }
   1148 
   1149   //
   1150   // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between
   1151   // real NIC handle and the virtual IPv6 NIC handle.
   1152   //
   1153   Status = gBS->OpenProtocol (
   1154                   ControllerHandle,
   1155                   &gEfiCallerIdGuid,
   1156                   (VOID **) &Id,
   1157                   This->DriverBindingHandle,
   1158                   Private->Ip6Nic->Controller,
   1159                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
   1160                   );
   1161   if (EFI_ERROR (Status)) {
   1162     goto ON_ERROR;
   1163   }
   1164 
   1165   //
   1166   // Set IPv6 avaiable flag and set default configure data for
   1167   // Udp6Read and Ip6 instance.
   1168   //
   1169   Status = PxeBcCheckIpv6Support (ControllerHandle, Private, &Private->Mode.Ipv6Available);
   1170   if (EFI_ERROR (Status)) {
   1171     //
   1172     // Fail to get the data whether UNDI supports IPv6. Set default value.
   1173     //
   1174     Private->Mode.Ipv6Available   = TRUE;
   1175   }
   1176 
   1177   if (!Private->Mode.Ipv6Available) {
   1178     goto ON_ERROR;
   1179   }
   1180 
   1181   Udp6CfgData                     = &Private->Udp6CfgData;
   1182   Ip6CfgData                      = &Private->Ip6CfgData;
   1183 
   1184   Udp6CfgData->AcceptAnyPort      = TRUE;
   1185   Udp6CfgData->AllowDuplicatePort = TRUE;
   1186   Udp6CfgData->HopLimit           = PXEBC_DEFAULT_HOPLIMIT;
   1187   Udp6CfgData->ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
   1188   Udp6CfgData->TransmitTimeout    = PXEBC_DEFAULT_LIFETIME;
   1189 
   1190   Ip6CfgData->AcceptIcmpErrors    = TRUE;
   1191   Ip6CfgData->DefaultProtocol     = IP6_ICMP;
   1192   Ip6CfgData->HopLimit            = PXEBC_DEFAULT_HOPLIMIT;
   1193   Ip6CfgData->ReceiveTimeout      = PXEBC_DEFAULT_LIFETIME;
   1194   Ip6CfgData->TransmitTimeout     = PXEBC_DEFAULT_LIFETIME;
   1195 
   1196   return EFI_SUCCESS;
   1197 
   1198 ON_ERROR:
   1199   PxeBcDestroyIp6Children (This, Private);
   1200   return Status;
   1201 }
   1202 
   1203 
   1204 /**
   1205   The entry point for UefiPxeBc driver that installs the driver
   1206   binding and component name protocol on its image.
   1207 
   1208   @param[in]  ImageHandle          The Image handle of the driver.
   1209   @param[in]  SystemTable          The system table.
   1210 
   1211   @return EFI_SUCCESS
   1212   @return Others
   1213 
   1214 **/
   1215 EFI_STATUS
   1216 EFIAPI
   1217 PxeBcDriverEntryPoint (
   1218   IN EFI_HANDLE             ImageHandle,
   1219   IN EFI_SYSTEM_TABLE       *SystemTable
   1220   )
   1221 {
   1222   EFI_STATUS  Status;
   1223 
   1224   Status = EfiLibInstallDriverBindingComponentName2 (
   1225              ImageHandle,
   1226              SystemTable,
   1227              &gPxeBcIp4DriverBinding,
   1228              ImageHandle,
   1229              &gPxeBcComponentName,
   1230              &gPxeBcComponentName2
   1231              );
   1232   if (EFI_ERROR (Status)) {
   1233     return Status;
   1234   }
   1235 
   1236   Status = EfiLibInstallDriverBindingComponentName2 (
   1237              ImageHandle,
   1238              SystemTable,
   1239              &gPxeBcIp6DriverBinding,
   1240              NULL,
   1241              &gPxeBcComponentName,
   1242              &gPxeBcComponentName2
   1243              );
   1244   if (EFI_ERROR (Status)) {
   1245     gBS->UninstallMultipleProtocolInterfaces (
   1246            ImageHandle,
   1247            &gEfiDriverBindingProtocolGuid,
   1248            &gPxeBcIp4DriverBinding,
   1249            &gEfiComponentName2ProtocolGuid,
   1250            &gPxeBcComponentName2,
   1251            &gEfiComponentNameProtocolGuid,
   1252            &gPxeBcComponentName,
   1253            NULL
   1254            );
   1255   }
   1256 
   1257   return Status;
   1258 }
   1259 
   1260 /**
   1261   Test to see if this driver supports ControllerHandle. This is the worker function for
   1262   PxeBcIp4(6)DriverBindingSupported.
   1263 
   1264   @param[in]  This                The pointer to the driver binding protocol.
   1265   @param[in]  ControllerHandle    The handle of device to be tested.
   1266   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
   1267                                   device to be started.
   1268   @param[in]  IpVersion           IP_VERSION_4 or IP_VERSION_6.
   1269 
   1270   @retval EFI_SUCCESS         This driver supports this device.
   1271   @retval EFI_UNSUPPORTED     This driver does not support this device.
   1272 
   1273 **/
   1274 EFI_STATUS
   1275 EFIAPI
   1276 PxeBcSupported (
   1277   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1278   IN EFI_HANDLE                   ControllerHandle,
   1279   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
   1280   IN UINT8                        IpVersion
   1281   )
   1282 {
   1283   EFI_STATUS                      Status;
   1284   EFI_GUID                        *DhcpServiceBindingGuid;
   1285   EFI_GUID                        *MtftpServiceBindingGuid;
   1286 
   1287   if (IpVersion == IP_VERSION_4) {
   1288     DhcpServiceBindingGuid  = &gEfiDhcp4ServiceBindingProtocolGuid;
   1289     MtftpServiceBindingGuid = &gEfiMtftp4ServiceBindingProtocolGuid;
   1290   } else {
   1291     DhcpServiceBindingGuid  = &gEfiDhcp6ServiceBindingProtocolGuid;
   1292     MtftpServiceBindingGuid = &gEfiMtftp6ServiceBindingProtocolGuid;
   1293   }
   1294 
   1295   //
   1296   // Try to open the Mtftp and Dhcp protocol to test whether IP stack is ready.
   1297   //
   1298   Status = gBS->OpenProtocol (
   1299                      ControllerHandle,
   1300                      DhcpServiceBindingGuid,
   1301                      NULL,
   1302                      This->DriverBindingHandle,
   1303                      ControllerHandle,
   1304                      EFI_OPEN_PROTOCOL_TEST_PROTOCOL
   1305                      );
   1306   if (!EFI_ERROR (Status)) {
   1307     Status = gBS->OpenProtocol (
   1308                        ControllerHandle,
   1309                        MtftpServiceBindingGuid,
   1310                        NULL,
   1311                        This->DriverBindingHandle,
   1312                        ControllerHandle,
   1313                        EFI_OPEN_PROTOCOL_TEST_PROTOCOL
   1314                        );
   1315   }
   1316 
   1317   //
   1318   // It's unsupported case if IP stack are not ready.
   1319   //
   1320   if (EFI_ERROR (Status)) {
   1321     return EFI_UNSUPPORTED;
   1322   }
   1323 
   1324   return EFI_SUCCESS;
   1325 }
   1326 
   1327 /**
   1328   Start this driver on ControllerHandle. This is the worker function for
   1329   PxeBcIp4(6)DriverBindingStart.
   1330 
   1331   @param[in]  This                 The pointer to the driver binding protocol.
   1332   @param[in]  ControllerHandle     The handle of device to be started.
   1333   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
   1334                                    device to be started.
   1335   @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
   1336 
   1337 
   1338   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
   1339   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
   1340   @retval other                This driver does not support this device.
   1341 
   1342 **/
   1343 EFI_STATUS
   1344 EFIAPI
   1345 PxeBcStart (
   1346   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1347   IN EFI_HANDLE                   ControllerHandle,
   1348   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
   1349   IN UINT8                        IpVersion
   1350   )
   1351 {
   1352   PXEBC_PRIVATE_DATA              *Private;
   1353   EFI_STATUS                      Status;
   1354   PXEBC_PRIVATE_PROTOCOL          *Id;
   1355   BOOLEAN                         FirstStart;
   1356 
   1357   FirstStart = FALSE;
   1358   Status = gBS->OpenProtocol (
   1359                   ControllerHandle,
   1360                   &gEfiCallerIdGuid,
   1361                   (VOID **) &Id,
   1362                   This->DriverBindingHandle,
   1363                   ControllerHandle,
   1364                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1365                   );
   1366   if (!EFI_ERROR (Status)) {
   1367     //
   1368     // Skip the initialization if the driver has been started already.
   1369     //
   1370     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
   1371   } else {
   1372     FirstStart = TRUE;
   1373     //
   1374     // If the driver has not been started yet, it should do initialization.
   1375     //
   1376     Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
   1377     if (Private == NULL) {
   1378       return EFI_OUT_OF_RESOURCES;
   1379     }
   1380 
   1381     CopyMem (
   1382       &Private->PxeBc,
   1383       &gPxeBcProtocolTemplate,
   1384       sizeof (EFI_PXE_BASE_CODE_PROTOCOL)
   1385       );
   1386 
   1387     Private->Signature          = PXEBC_PRIVATE_DATA_SIGNATURE;
   1388     Private->Controller         = ControllerHandle;
   1389     Private->Image              = This->ImageHandle;
   1390     Private->PxeBc.Mode         = &Private->Mode;
   1391     Private->Mode.Ipv6Supported = TRUE;
   1392     Private->Mode.AutoArp       = TRUE;
   1393     Private->Mode.TTL           = DEFAULT_TTL;
   1394     Private->Mode.ToS           = DEFAULT_ToS;
   1395 
   1396     //
   1397     // Open device path to prepare for appending virtual NIC node.
   1398     //
   1399     Status = gBS->OpenProtocol (
   1400                     ControllerHandle,
   1401                     &gEfiDevicePathProtocolGuid,
   1402                     (VOID **) &Private->DevicePath,
   1403                     This->DriverBindingHandle,
   1404                     ControllerHandle,
   1405                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1406                     );
   1407 
   1408     if (EFI_ERROR (Status)) {
   1409       goto ON_ERROR;
   1410     }
   1411 
   1412     //
   1413     // Get the NII interface if it exists, it's not required.
   1414     //
   1415     Status = gBS->OpenProtocol (
   1416                     ControllerHandle,
   1417                     &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
   1418                     (VOID **) &Private->Nii,
   1419                     This->DriverBindingHandle,
   1420                     ControllerHandle,
   1421                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1422                     );
   1423     if (EFI_ERROR (Status)) {
   1424       Private->Nii = NULL;
   1425     }
   1426 
   1427     //
   1428     // Install PxeBaseCodePrivate protocol onto the real NIC handler.
   1429     // PxeBaseCodePrivate protocol is only used to keep the relationship between
   1430     // NIC handle and virtual child handles.
   1431     // gEfiCallerIdGuid will be used as its protocol guid.
   1432     //
   1433     Status = gBS->InstallProtocolInterface (
   1434                     &ControllerHandle,
   1435                     &gEfiCallerIdGuid,
   1436                     EFI_NATIVE_INTERFACE,
   1437                     &Private->Id
   1438                     );
   1439     if (EFI_ERROR (Status)) {
   1440       goto ON_ERROR;
   1441     }
   1442 
   1443     //
   1444     // Try to locate SNP protocol.
   1445     //
   1446     NetLibGetSnpHandle(ControllerHandle, &Private->Snp);
   1447   }
   1448 
   1449   if (IpVersion == IP_VERSION_4) {
   1450     //
   1451     // Try to create virtual NIC handle for IPv4.
   1452     //
   1453     Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);
   1454   } else {
   1455     //
   1456     // Try to create virtual NIC handle for IPv6.
   1457     //
   1458     Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);
   1459   }
   1460   if (EFI_ERROR (Status)) {
   1461     //
   1462     // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.
   1463     //
   1464     Status = EFI_DEVICE_ERROR;
   1465     goto ON_ERROR;
   1466   }
   1467 
   1468   return EFI_SUCCESS;
   1469 
   1470 ON_ERROR:
   1471   if (FirstStart) {
   1472     gBS->UninstallProtocolInterface (
   1473            ControllerHandle,
   1474            &gEfiCallerIdGuid,
   1475            &Private->Id
   1476            );
   1477   }
   1478 
   1479   if (IpVersion == IP_VERSION_4) {
   1480     PxeBcDestroyIp4Children (This, Private);
   1481   } else {
   1482     PxeBcDestroyIp6Children (This, Private);
   1483   }
   1484 
   1485   if (FirstStart && Private != NULL) {
   1486     FreePool (Private);
   1487   }
   1488 
   1489   return Status;
   1490 }
   1491 
   1492 
   1493 /**
   1494   Stop this driver on ControllerHandle. This is the worker function for
   1495   PxeBcIp4(6)DriverBindingStop.
   1496 
   1497   @param[in]  This              Protocol instance pointer.
   1498   @param[in]  ControllerHandle  Handle of device to stop driver on.
   1499   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
   1500                                 children is zero stop the entire bus driver.
   1501   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
   1502   @param[in]  IpVersion         IP_VERSION_4 or IP_VERSION_6.
   1503 
   1504   @retval EFI_SUCCESS           This driver was removed ControllerHandle.
   1505   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
   1506   @retval Others                This driver was not removed from this device
   1507 
   1508 **/
   1509 EFI_STATUS
   1510 EFIAPI
   1511 PxeBcStop (
   1512   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1513   IN EFI_HANDLE                   ControllerHandle,
   1514   IN UINTN                        NumberOfChildren,
   1515   IN EFI_HANDLE                   *ChildHandleBuffer,
   1516   IN UINT8                        IpVersion
   1517   )
   1518 {
   1519   PXEBC_PRIVATE_DATA              *Private;
   1520   PXEBC_VIRTUAL_NIC               *VirtualNic;
   1521   EFI_LOAD_FILE_PROTOCOL          *LoadFile;
   1522   EFI_STATUS                      Status;
   1523   EFI_HANDLE                      NicHandle;
   1524   PXEBC_PRIVATE_PROTOCOL          *Id;
   1525 
   1526   Private    = NULL;
   1527   NicHandle  = NULL;
   1528   VirtualNic = NULL;
   1529   LoadFile   = NULL;
   1530   Id         = NULL;
   1531 
   1532   Status = gBS->OpenProtocol (
   1533                   ControllerHandle,
   1534                   &gEfiLoadFileProtocolGuid,
   1535                   (VOID **) &LoadFile,
   1536                   This->DriverBindingHandle,
   1537                   ControllerHandle,
   1538                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1539                   );
   1540   if (EFI_ERROR (Status)) {
   1541     //
   1542     // Get the Nic handle by any pass-over service child handle.
   1543     //
   1544     if (IpVersion == IP_VERSION_4) {
   1545       NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);
   1546     } else {
   1547       NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);
   1548     }
   1549     if (NicHandle == NULL) {
   1550       return EFI_SUCCESS;
   1551     }
   1552 
   1553     //
   1554     // Try to retrieve the private data by PxeBcPrivate protocol.
   1555     //
   1556     Status = gBS->OpenProtocol (
   1557                     NicHandle,
   1558                     &gEfiCallerIdGuid,
   1559                     (VOID **) &Id,
   1560                     This->DriverBindingHandle,
   1561                     ControllerHandle,
   1562                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1563                     );
   1564     if (EFI_ERROR (Status)) {
   1565       return Status;
   1566     }
   1567     Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);
   1568 
   1569   } else {
   1570     //
   1571     // It's a virtual handle with LoadFileProtocol.
   1572     //
   1573     Status = gBS->OpenProtocol (
   1574                     ControllerHandle,
   1575                     &gEfiLoadFileProtocolGuid,
   1576                     (VOID **) &LoadFile,
   1577                     This->DriverBindingHandle,
   1578                     ControllerHandle,
   1579                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1580                     );
   1581     if (EFI_ERROR (Status)) {
   1582       return Status;
   1583     }
   1584 
   1585     VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);
   1586     Private    = VirtualNic->Private;
   1587     NicHandle  = Private->Controller;
   1588   }
   1589 
   1590   //
   1591   // Stop functionality of PXE Base Code protocol
   1592   //
   1593   Status = Private->PxeBc.Stop (&Private->PxeBc);
   1594   if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
   1595     return Status;
   1596   }
   1597 
   1598 
   1599   if (Private->Ip4Nic != NULL && IpVersion == IP_VERSION_4) {
   1600     PxeBcDestroyIp4Children (This, Private);
   1601   }
   1602 
   1603   if (Private->Ip6Nic != NULL && IpVersion == IP_VERSION_6) {
   1604     PxeBcDestroyIp6Children (This, Private);
   1605   }
   1606 
   1607   if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {
   1608     gBS->UninstallProtocolInterface (
   1609            NicHandle,
   1610            &gEfiCallerIdGuid,
   1611            &Private->Id
   1612            );
   1613     FreePool (Private);
   1614   }
   1615 
   1616   return EFI_SUCCESS;
   1617 }
   1618 
   1619 /**
   1620   Test to see if this driver supports ControllerHandle. This service
   1621   is called by the EFI boot service ConnectController(). In
   1622   order to make drivers as small as possible, there are a few calling
   1623   restrictions for this service. ConnectController() must
   1624   follow these calling restrictions. If any other agent wishes to call
   1625   Supported() it must also follow these calling restrictions.
   1626 
   1627   @param[in]  This                The pointer to the driver binding protocol.
   1628   @param[in]  ControllerHandle    The handle of device to be tested.
   1629   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
   1630                                   device to be started.
   1631 
   1632   @retval EFI_SUCCESS         This driver supports this device.
   1633   @retval EFI_UNSUPPORTED     This driver does not support this device.
   1634 
   1635 **/
   1636 EFI_STATUS
   1637 EFIAPI
   1638 PxeBcIp4DriverBindingSupported (
   1639   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1640   IN EFI_HANDLE                   ControllerHandle,
   1641   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1642   )
   1643 {
   1644   return PxeBcSupported (
   1645            This,
   1646            ControllerHandle,
   1647            RemainingDevicePath,
   1648            IP_VERSION_4
   1649            );
   1650 }
   1651 
   1652 /**
   1653   Start this driver on ControllerHandle. This service is called by the
   1654   EFI boot service ConnectController(). In order to make
   1655   drivers as small as possible, there are a few calling restrictions for
   1656   this service. ConnectController() must follow these
   1657   calling restrictions. If any other agent wishes to call Start() it
   1658   must also follow these calling restrictions.
   1659 
   1660   @param[in]  This                 The pointer to the driver binding protocol.
   1661   @param[in]  ControllerHandle     The handle of device to be started.
   1662   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
   1663                                    device to be started.
   1664 
   1665   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
   1666   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
   1667   @retval other                This driver does not support this device.
   1668 
   1669 **/
   1670 EFI_STATUS
   1671 EFIAPI
   1672 PxeBcIp4DriverBindingStart (
   1673   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1674   IN EFI_HANDLE                   ControllerHandle,
   1675   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1676   )
   1677 {
   1678   return PxeBcStart (
   1679            This,
   1680            ControllerHandle,
   1681            RemainingDevicePath,
   1682            IP_VERSION_4
   1683            );
   1684 }
   1685 
   1686 /**
   1687   Stop this driver on ControllerHandle. This service is called by the
   1688   EFI boot service DisconnectController(). In order to
   1689   make drivers as small as possible, there are a few calling
   1690   restrictions for this service. DisconnectController()
   1691   must follow these calling restrictions. If any other agent wishes
   1692   to call Stop() it must also follow these calling restrictions.
   1693 
   1694   @param[in]  This              Protocol instance pointer.
   1695   @param[in]  ControllerHandle  Handle of device to stop driver on
   1696   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
   1697                                 children is zero stop the entire bus driver.
   1698   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
   1699 
   1700   @retval EFI_SUCCESS           This driver is removed ControllerHandle
   1701   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
   1702   @retval Others                This driver was not removed from this device.
   1703 
   1704 **/
   1705 EFI_STATUS
   1706 EFIAPI
   1707 PxeBcIp4DriverBindingStop (
   1708   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1709   IN EFI_HANDLE                   ControllerHandle,
   1710   IN UINTN                        NumberOfChildren,
   1711   IN EFI_HANDLE                   *ChildHandleBuffer
   1712   )
   1713 {
   1714   return PxeBcStop (
   1715            This,
   1716            ControllerHandle,
   1717            NumberOfChildren,
   1718            ChildHandleBuffer,
   1719            IP_VERSION_4
   1720            );
   1721 }
   1722 
   1723 /**
   1724   Test to see if this driver supports ControllerHandle. This service
   1725   is called by the EFI boot service ConnectController(). In
   1726   order to make drivers as small as possible, there are a few calling
   1727   restrictions for this service. ConnectController() must
   1728   follow these calling restrictions. If any other agent wishes to call
   1729   Supported() it must also follow these calling restrictions.
   1730 
   1731   @param[in]  This                The pointer to the driver binding protocol.
   1732   @param[in]  ControllerHandle    The handle of device to be tested.
   1733   @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
   1734                                   device to be started.
   1735 
   1736   @retval EFI_SUCCESS         This driver supports this device.
   1737   @retval EFI_UNSUPPORTED     This driver does not support this device.
   1738 
   1739 **/
   1740 EFI_STATUS
   1741 EFIAPI
   1742 PxeBcIp6DriverBindingSupported (
   1743   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1744   IN EFI_HANDLE                   ControllerHandle,
   1745   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1746   )
   1747 {
   1748   return PxeBcSupported (
   1749            This,
   1750            ControllerHandle,
   1751            RemainingDevicePath,
   1752            IP_VERSION_6
   1753            );
   1754 }
   1755 
   1756 /**
   1757   Start this driver on ControllerHandle. This service is called by the
   1758   EFI boot service ConnectController(). In order to make
   1759   drivers as small as possible, there are a few calling restrictions for
   1760   this service. ConnectController() must follow these
   1761   calling restrictions. If any other agent wishes to call Start() it
   1762   must also follow these calling restrictions.
   1763 
   1764   @param[in]  This                 The pointer to the driver binding protocol.
   1765   @param[in]  ControllerHandle     The handle of device to be started.
   1766   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
   1767                                    device to be started.
   1768 
   1769   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
   1770   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
   1771   @retval other                This driver does not support this device.
   1772 
   1773 **/
   1774 EFI_STATUS
   1775 EFIAPI
   1776 PxeBcIp6DriverBindingStart (
   1777   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1778   IN EFI_HANDLE                   ControllerHandle,
   1779   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
   1780   )
   1781 {
   1782   return PxeBcStart (
   1783            This,
   1784            ControllerHandle,
   1785            RemainingDevicePath,
   1786            IP_VERSION_6
   1787            );
   1788 }
   1789 
   1790 /**
   1791   Stop this driver on ControllerHandle. This service is called by the
   1792   EFI boot service DisconnectController(). In order to
   1793   make drivers as small as possible, there are a few calling
   1794   restrictions for this service. DisconnectController()
   1795   must follow these calling restrictions. If any other agent wishes
   1796   to call Stop() it must also follow these calling restrictions.
   1797 
   1798   @param[in]  This              Protocol instance pointer.
   1799   @param[in]  ControllerHandle  Handle of device to stop driver on
   1800   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
   1801                                 children is zero stop the entire bus driver.
   1802   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
   1803 
   1804   @retval EFI_SUCCESS           This driver is removed ControllerHandle
   1805   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
   1806   @retval Others                This driver was not removed from this device.
   1807 
   1808 **/
   1809 EFI_STATUS
   1810 EFIAPI
   1811 PxeBcIp6DriverBindingStop (
   1812   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
   1813   IN EFI_HANDLE                   ControllerHandle,
   1814   IN UINTN                        NumberOfChildren,
   1815   IN EFI_HANDLE                   *ChildHandleBuffer
   1816   )
   1817 {
   1818   return PxeBcStop (
   1819            This,
   1820            ControllerHandle,
   1821            NumberOfChildren,
   1822            ChildHandleBuffer,
   1823            IP_VERSION_6
   1824            );
   1825 }
   1826