Home | History | Annotate | Download | only in UefiPxeBcDxe
      1 /** @file
      2   The driver binding for UEFI PXEBC protocol.
      3 
      4 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 
     16 #include "PxeBcImpl.h"
     17 
     18 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {
     19   PxeBcDriverBindingSupported,
     20   PxeBcDriverBindingStart,
     21   PxeBcDriverBindingStop,
     22   0xa,
     23   NULL,
     24   NULL
     25 };
     26 
     27 /**
     28   This is the declaration of an EFI image entry point. This entry point is
     29   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
     30   both device drivers and bus drivers.
     31 
     32   @param  ImageHandle           The firmware allocated handle for the UEFI image.
     33   @param  SystemTable           A pointer to the EFI System Table.
     34 
     35   @retval EFI_SUCCESS           The operation completed successfully.
     36   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
     37 
     38 **/
     39 EFI_STATUS
     40 EFIAPI
     41 PxeBcDriverEntryPoint (
     42   IN EFI_HANDLE             ImageHandle,
     43   IN EFI_SYSTEM_TABLE       *SystemTable
     44   )
     45 {
     46   return EfiLibInstallDriverBindingComponentName2 (
     47           ImageHandle,
     48           SystemTable,
     49           &gPxeBcDriverBinding,
     50           ImageHandle,
     51           &gPxeBcComponentName,
     52           &gPxeBcComponentName2
     53           );
     54 }
     55 
     56 
     57 /**
     58   Test to see if this driver supports ControllerHandle. This service
     59   is called by the EFI boot service ConnectController(). In
     60   order to make drivers as small as possible, there are a few calling
     61   restrictions for this service. ConnectController() must
     62   follow these calling restrictions. If any other agent wishes to call
     63   Supported() it must also follow these calling restrictions.
     64   PxeBc requires DHCP4 and MTFTP4 protocols.
     65 
     66   @param  This                Protocol instance pointer.
     67   @param  ControllerHandle    Handle of device to test
     68   @param  RemainingDevicePath Optional parameter use to pick a specific child
     69                               device to start.
     70 
     71   @retval EFI_SUCCESS         This driver supports this device
     72   @retval EFI_ALREADY_STARTED This driver is already running on this device
     73   @retval other               This driver does not support this device
     74 
     75 **/
     76 EFI_STATUS
     77 EFIAPI
     78 PxeBcDriverBindingSupported (
     79   IN EFI_DRIVER_BINDING_PROTOCOL  * This,
     80   IN EFI_HANDLE                   ControllerHandle,
     81   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL
     82   )
     83 {
     84   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;
     85   EFI_STATUS                  Status;
     86 
     87   Status = gBS->OpenProtocol (
     88                   ControllerHandle,
     89                   &gEfiPxeBaseCodeProtocolGuid,
     90                   (VOID **) &PxeBc,
     91                   This->DriverBindingHandle,
     92                   ControllerHandle,
     93                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
     94                   );
     95 
     96   if (!EFI_ERROR (Status)) {
     97     return EFI_ALREADY_STARTED;
     98   }
     99 
    100   Status = gBS->OpenProtocol (
    101                   ControllerHandle,
    102                   &gEfiDhcp4ServiceBindingProtocolGuid,
    103                   NULL,
    104                   This->DriverBindingHandle,
    105                   ControllerHandle,
    106                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    107                   );
    108 
    109   if (!EFI_ERROR (Status)) {
    110 
    111     Status = gBS->OpenProtocol (
    112                     ControllerHandle,
    113                     &gEfiMtftp4ServiceBindingProtocolGuid,
    114                     NULL,
    115                     This->DriverBindingHandle,
    116                     ControllerHandle,
    117                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    118                     );
    119 
    120   }
    121 
    122   return Status;
    123 }
    124 
    125 
    126 /**
    127   Start this driver on ControllerHandle. This service is called by the
    128   EFI boot service ConnectController(). In order to make
    129   drivers as small as possible, there are a few calling restrictions for
    130   this service. ConnectController() must follow these
    131   calling restrictions. If any other agent wishes to call Start() it
    132   must also follow these calling restrictions.
    133 
    134   @param  This                 Protocol instance pointer.
    135   @param  ControllerHandle     Handle of device to bind driver to
    136   @param  RemainingDevicePath  Optional parameter use to pick a specific child
    137                                device to start.
    138 
    139   @retval EFI_SUCCESS          This driver is added to ControllerHandle
    140   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
    141   @retval other                This driver does not support this device
    142 
    143 **/
    144 EFI_STATUS
    145 EFIAPI
    146 PxeBcDriverBindingStart (
    147   IN EFI_DRIVER_BINDING_PROTOCOL  * This,
    148   IN EFI_HANDLE                   ControllerHandle,
    149   IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL
    150   )
    151 {
    152   PXEBC_PRIVATE_DATA  *Private;
    153   UINTN               Index;
    154   EFI_STATUS          Status;
    155   EFI_IP4_MODE_DATA   Ip4ModeData;
    156 
    157   Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
    158   if (Private == NULL) {
    159     return EFI_OUT_OF_RESOURCES;
    160   }
    161 
    162   Private->Signature                    = PXEBC_PRIVATE_DATA_SIGNATURE;
    163   Private->Controller                   = ControllerHandle;
    164   Private->Image                        = This->DriverBindingHandle;
    165   CopyMem (&Private->PxeBc, &mPxeBcProtocolTemplate, sizeof (Private->PxeBc));
    166   Private->PxeBc.Mode                   = &Private->Mode;
    167   CopyMem (&Private->LoadFile, &mLoadFileProtocolTemplate, sizeof (Private->LoadFile));
    168 
    169   Private->ProxyOffer.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
    170   Private->Dhcp4Ack.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
    171   Private->PxeReply.Packet.Ack.Size     = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
    172 
    173   for (Index = 0; Index < PXEBC_MAX_OFFER_NUM; Index++) {
    174     Private->Dhcp4Offers[Index].Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
    175   }
    176 
    177   //
    178   // Get the NII interface if it exists.
    179   //
    180   Status = gBS->OpenProtocol (
    181                   ControllerHandle,
    182                   &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
    183                   (VOID **) &Private->Nii,
    184                   This->DriverBindingHandle,
    185                   ControllerHandle,
    186                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    187                   );
    188   if (EFI_ERROR (Status)) {
    189     Private->Nii = NULL;
    190   }
    191 
    192   Status = NetLibCreateServiceChild (
    193             ControllerHandle,
    194             This->DriverBindingHandle,
    195             &gEfiArpServiceBindingProtocolGuid,
    196             &Private->ArpChild
    197             );
    198   if (EFI_ERROR (Status)) {
    199     goto ON_ERROR;
    200   }
    201 
    202   Status = gBS->OpenProtocol (
    203                   Private->ArpChild,
    204                   &gEfiArpProtocolGuid,
    205                   (VOID **) &Private->Arp,
    206                   This->DriverBindingHandle,
    207                   ControllerHandle,
    208                   EFI_OPEN_PROTOCOL_BY_DRIVER
    209                   );
    210   if (EFI_ERROR (Status)) {
    211     goto ON_ERROR;
    212   }
    213 
    214   Status = NetLibCreateServiceChild (
    215             ControllerHandle,
    216             This->DriverBindingHandle,
    217             &gEfiDhcp4ServiceBindingProtocolGuid,
    218             &Private->Dhcp4Child
    219             );
    220   if (EFI_ERROR (Status)) {
    221     goto ON_ERROR;
    222   }
    223 
    224   Status = gBS->OpenProtocol (
    225                   Private->Dhcp4Child,
    226                   &gEfiDhcp4ProtocolGuid,
    227                   (VOID **) &Private->Dhcp4,
    228                   This->DriverBindingHandle,
    229                   ControllerHandle,
    230                   EFI_OPEN_PROTOCOL_BY_DRIVER
    231                   );
    232   if (EFI_ERROR (Status)) {
    233     goto ON_ERROR;
    234   }
    235 
    236   Status = NetLibCreateServiceChild (
    237              ControllerHandle,
    238              This->DriverBindingHandle,
    239              &gEfiIp4ServiceBindingProtocolGuid,
    240              &Private->Ip4Child
    241              );
    242   if (EFI_ERROR (Status)) {
    243     goto ON_ERROR;
    244   }
    245 
    246   Status = gBS->OpenProtocol (
    247                   Private->Ip4Child,
    248                   &gEfiIp4ProtocolGuid,
    249                   (VOID **) &Private->Ip4,
    250                   This->DriverBindingHandle,
    251                   ControllerHandle,
    252                   EFI_OPEN_PROTOCOL_BY_DRIVER
    253                   );
    254   if (EFI_ERROR (Status)) {
    255     goto ON_ERROR;
    256   }
    257 
    258   //
    259   // Get max packet size from Ip4 to calculate block size for Tftp later.
    260   //
    261   Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
    262   if (EFI_ERROR (Status)) {
    263     goto ON_ERROR;
    264   }
    265 
    266   Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;
    267 
    268   Status = NetLibCreateServiceChild (
    269              ControllerHandle,
    270              This->DriverBindingHandle,
    271              &gEfiMtftp4ServiceBindingProtocolGuid,
    272              &Private->Mtftp4Child
    273              );
    274 
    275   if (EFI_ERROR (Status)) {
    276     goto ON_ERROR;
    277   }
    278 
    279   Status = gBS->OpenProtocol (
    280                   Private->Mtftp4Child,
    281                   &gEfiMtftp4ProtocolGuid,
    282                   (VOID **) &Private->Mtftp4,
    283                   This->DriverBindingHandle,
    284                   ControllerHandle,
    285                   EFI_OPEN_PROTOCOL_BY_DRIVER
    286                   );
    287 
    288   if (EFI_ERROR (Status)) {
    289     goto ON_ERROR;
    290   }
    291 
    292   Status = NetLibCreateServiceChild (
    293              ControllerHandle,
    294              This->DriverBindingHandle,
    295              &gEfiUdp4ServiceBindingProtocolGuid,
    296              &Private->Udp4ReadChild
    297              );
    298 
    299   if (EFI_ERROR (Status)) {
    300     goto ON_ERROR;
    301   }
    302 
    303   //
    304   // The UDP instance for EfiPxeBcUdpRead
    305   //
    306   Status = gBS->OpenProtocol (
    307                   Private->Udp4ReadChild,
    308                   &gEfiUdp4ProtocolGuid,
    309                   (VOID **) &Private->Udp4Read,
    310                   This->DriverBindingHandle,
    311                   ControllerHandle,
    312                   EFI_OPEN_PROTOCOL_BY_DRIVER
    313                   );
    314 
    315   if (EFI_ERROR (Status)) {
    316     goto ON_ERROR;
    317   }
    318 
    319   //
    320   // The UDP instance for EfiPxeBcUdpWrite
    321   //
    322   Status = NetLibCreateServiceChild (
    323              ControllerHandle,
    324              This->DriverBindingHandle,
    325              &gEfiUdp4ServiceBindingProtocolGuid,
    326              &Private->Udp4WriteChild
    327              );
    328   if (EFI_ERROR (Status)) {
    329     goto ON_ERROR;
    330   }
    331 
    332   Status = gBS->OpenProtocol (
    333                   Private->Udp4WriteChild,
    334                   &gEfiUdp4ProtocolGuid,
    335                   (VOID **) &Private->Udp4Write,
    336                   This->DriverBindingHandle,
    337                   ControllerHandle,
    338                   EFI_OPEN_PROTOCOL_BY_DRIVER
    339                   );
    340   if (EFI_ERROR (Status)) {
    341     goto ON_ERROR;
    342   }
    343   ZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA));
    344   Private->Udp4CfgData.AcceptBroadcast    = FALSE;
    345   Private->Udp4CfgData.AcceptPromiscuous  = FALSE;
    346   Private->Udp4CfgData.AcceptAnyPort      = TRUE;
    347   Private->Udp4CfgData.AllowDuplicatePort = TRUE;
    348   Private->Udp4CfgData.TypeOfService      = DEFAULT_ToS;
    349   Private->Udp4CfgData.TimeToLive         = DEFAULT_TTL;
    350   Private->Udp4CfgData.DoNotFragment      = FALSE;
    351   Private->Udp4CfgData.ReceiveTimeout     = PXEBC_DEFAULT_LIFETIME;
    352   Private->Udp4CfgData.UseDefaultAddress  = FALSE;
    353 
    354   PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4Read);
    355   Private->MacLen = Private->SeedPacket.Dhcp4.Header.HwAddrLen;
    356   CopyMem (&Private->Mac, &Private->SeedPacket.Dhcp4.Header.ClientHwAddr[0], Private->MacLen);
    357 
    358 
    359   ZeroMem (&Private->Ip4ConfigData, sizeof (EFI_IP4_CONFIG_DATA));
    360   Private->Ip4ConfigData.DefaultProtocol   = EFI_IP_PROTO_ICMP;
    361   Private->Ip4ConfigData.AcceptIcmpErrors  = TRUE;
    362   Private->Ip4ConfigData.TypeOfService     = DEFAULT_ToS;
    363   Private->Ip4ConfigData.TimeToLive        = DEFAULT_TTL;
    364   Private->Ip4ConfigData.DoNotFragment     = FALSE;
    365   Private->Ip4ConfigData.RawData           = FALSE;
    366 
    367   Status = gBS->InstallMultipleProtocolInterfaces (
    368                   &ControllerHandle,
    369                   &gEfiPxeBaseCodeProtocolGuid,
    370                   &Private->PxeBc,
    371                   &gEfiLoadFileProtocolGuid,
    372                   &Private->LoadFile,
    373                   NULL
    374                   );
    375   if (EFI_ERROR (Status)) {
    376     goto ON_ERROR;
    377   }
    378   //
    379   // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.
    380   //
    381   Status = gBS->HandleProtocol (
    382                   ControllerHandle,
    383                   &gEfiIp4Config2ProtocolGuid,
    384                   (VOID **) &Private->Ip4Config2
    385                   );
    386   if (EFI_ERROR (Status)) {
    387     goto ON_ERROR;
    388   }
    389 
    390   return EFI_SUCCESS;
    391 
    392 ON_ERROR:
    393 
    394   if (Private->Udp4WriteChild != NULL) {
    395     gBS->CloseProtocol (
    396            Private->Udp4WriteChild,
    397            &gEfiUdp4ProtocolGuid,
    398            This->DriverBindingHandle,
    399            ControllerHandle
    400            );
    401     NetLibDestroyServiceChild (
    402       ControllerHandle,
    403       This->DriverBindingHandle,
    404       &gEfiUdp4ServiceBindingProtocolGuid,
    405       Private->Udp4WriteChild
    406       );
    407   }
    408 
    409   if (Private->Udp4ReadChild != NULL) {
    410     gBS->CloseProtocol (
    411           Private->Udp4ReadChild,
    412           &gEfiUdp4ProtocolGuid,
    413           This->DriverBindingHandle,
    414           ControllerHandle
    415           );
    416     NetLibDestroyServiceChild (
    417       ControllerHandle,
    418       This->DriverBindingHandle,
    419       &gEfiUdp4ServiceBindingProtocolGuid,
    420       Private->Udp4ReadChild
    421       );
    422   }
    423 
    424   if (Private->Mtftp4Child != NULL) {
    425     gBS->CloseProtocol (
    426           Private->Mtftp4Child,
    427           &gEfiMtftp4ProtocolGuid,
    428           This->DriverBindingHandle,
    429           ControllerHandle
    430           );
    431 
    432     NetLibDestroyServiceChild (
    433       ControllerHandle,
    434       This->DriverBindingHandle,
    435       &gEfiMtftp4ServiceBindingProtocolGuid,
    436       Private->Mtftp4Child
    437       );
    438   }
    439 
    440   if (Private->Ip4Child != NULL) {
    441     gBS->CloseProtocol (
    442           Private->Ip4Child,
    443           &gEfiIp4ProtocolGuid,
    444           This->DriverBindingHandle,
    445           ControllerHandle
    446           );
    447 
    448     NetLibDestroyServiceChild (
    449       ControllerHandle,
    450       This->DriverBindingHandle,
    451       &gEfiIp4ServiceBindingProtocolGuid,
    452       Private->Ip4Child
    453       );
    454   }
    455 
    456   if (Private->Dhcp4Child != NULL) {
    457     gBS->CloseProtocol (
    458           Private->Dhcp4Child,
    459           &gEfiDhcp4ProtocolGuid,
    460           This->DriverBindingHandle,
    461           ControllerHandle
    462           );
    463 
    464     NetLibDestroyServiceChild (
    465       ControllerHandle,
    466       This->DriverBindingHandle,
    467       &gEfiDhcp4ServiceBindingProtocolGuid,
    468       Private->Dhcp4Child
    469       );
    470   }
    471 
    472   if (Private->ArpChild != NULL) {
    473     gBS->CloseProtocol (
    474           Private->ArpChild,
    475           &gEfiArpProtocolGuid,
    476           This->DriverBindingHandle,
    477           ControllerHandle
    478           );
    479 
    480     NetLibDestroyServiceChild (
    481       ControllerHandle,
    482       This->DriverBindingHandle,
    483       &gEfiArpServiceBindingProtocolGuid,
    484       Private->ArpChild
    485       );
    486   }
    487 
    488   FreePool (Private);
    489 
    490   return Status;
    491 }
    492 
    493 
    494 /**
    495   Stop this driver on ControllerHandle. This service is called by the
    496   EFI boot service DisconnectController(). In order to
    497   make drivers as small as possible, there are a few calling
    498   restrictions for this service. DisconnectController()
    499   must follow these calling restrictions. If any other agent wishes
    500   to call Stop() it must also follow these calling restrictions.
    501 
    502   @param  This              Protocol instance pointer.
    503   @param  ControllerHandle  Handle of device to stop driver on
    504   @param  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    505                             children is zero stop the entire bus driver.
    506   @param  ChildHandleBuffer List of Child Handles to Stop.
    507 
    508   @retval EFI_SUCCESS       This driver is removed ControllerHandle
    509   @retval other             This driver was not removed from this device
    510 
    511 **/
    512 EFI_STATUS
    513 EFIAPI
    514 PxeBcDriverBindingStop (
    515   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    516   IN EFI_HANDLE                   ControllerHandle,
    517   IN UINTN                        NumberOfChildren,
    518   IN EFI_HANDLE                   *ChildHandleBuffer
    519   )
    520 {
    521   PXEBC_PRIVATE_DATA          *Private;
    522   EFI_PXE_BASE_CODE_PROTOCOL  *PxeBc;
    523   EFI_HANDLE                  NicHandle;
    524   EFI_STATUS                  Status;
    525 
    526   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
    527   if (NicHandle == NULL) {
    528     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
    529 
    530     if (NicHandle == NULL) {
    531       NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
    532 
    533       if (NicHandle == NULL) {
    534         NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
    535 
    536         if (NicHandle == NULL) {
    537           NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
    538 
    539           if (NicHandle == NULL) {
    540             return EFI_SUCCESS;
    541           }
    542         }
    543       }
    544     }
    545   }
    546 
    547   Status = gBS->OpenProtocol (
    548                   NicHandle,
    549                   &gEfiPxeBaseCodeProtocolGuid,
    550                   (VOID **) &PxeBc,
    551                   This->DriverBindingHandle,
    552                   ControllerHandle,
    553                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    554                   );
    555 
    556   if (EFI_ERROR (Status)) {
    557     return Status;
    558   }
    559 
    560   //
    561   // Stop functionality of PXE Base Code protocol
    562   //
    563   Status = PxeBc->Stop (PxeBc);
    564   if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
    565     return Status;
    566   }
    567 
    568   Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);
    569 
    570   Status = gBS->UninstallMultipleProtocolInterfaces (
    571                   NicHandle,
    572                   &gEfiPxeBaseCodeProtocolGuid,
    573                   &Private->PxeBc,
    574                   &gEfiLoadFileProtocolGuid,
    575                   &Private->LoadFile,
    576                   NULL
    577                   );
    578 
    579   if (!EFI_ERROR (Status)) {
    580 
    581     gBS->CloseProtocol (
    582            Private->Udp4WriteChild,
    583            &gEfiUdp4ProtocolGuid,
    584            This->DriverBindingHandle,
    585            NicHandle
    586            );
    587     NetLibDestroyServiceChild (
    588       ControllerHandle,
    589       This->DriverBindingHandle,
    590       &gEfiUdp4ServiceBindingProtocolGuid,
    591       Private->Udp4WriteChild
    592       );
    593 
    594     gBS->CloseProtocol (
    595           Private->Udp4ReadChild,
    596           &gEfiUdp4ProtocolGuid,
    597           This->DriverBindingHandle,
    598           NicHandle
    599           );
    600     NetLibDestroyServiceChild (
    601       NicHandle,
    602       This->DriverBindingHandle,
    603       &gEfiUdp4ServiceBindingProtocolGuid,
    604       Private->Udp4ReadChild
    605       );
    606 
    607     gBS->CloseProtocol (
    608           Private->Dhcp4Child,
    609           &gEfiDhcp4ProtocolGuid,
    610           This->DriverBindingHandle,
    611           NicHandle
    612           );
    613     NetLibDestroyServiceChild (
    614       NicHandle,
    615       This->DriverBindingHandle,
    616       &gEfiDhcp4ServiceBindingProtocolGuid,
    617       Private->Dhcp4Child
    618       );
    619 
    620     gBS->CloseProtocol (
    621           Private->Mtftp4Child,
    622           &gEfiMtftp4ProtocolGuid,
    623           This->DriverBindingHandle,
    624           NicHandle
    625           );
    626     NetLibDestroyServiceChild (
    627       NicHandle,
    628       This->DriverBindingHandle,
    629       &gEfiMtftp4ServiceBindingProtocolGuid,
    630       Private->Mtftp4Child
    631       );
    632 
    633     gBS->CloseProtocol (
    634           Private->Ip4Child,
    635           &gEfiIp4ProtocolGuid,
    636           This->DriverBindingHandle,
    637           NicHandle
    638           );
    639     NetLibDestroyServiceChild (
    640       NicHandle,
    641       This->DriverBindingHandle,
    642       &gEfiIp4ServiceBindingProtocolGuid,
    643       Private->Ip4Child
    644       );
    645 
    646     gBS->CloseProtocol (
    647           Private->ArpChild,
    648           &gEfiArpProtocolGuid,
    649           This->DriverBindingHandle,
    650           NicHandle
    651           );
    652     NetLibDestroyServiceChild (
    653       NicHandle,
    654       This->DriverBindingHandle,
    655       &gEfiArpServiceBindingProtocolGuid,
    656       Private->ArpChild
    657       );
    658 
    659     FreePool (Private);
    660   }
    661 
    662   return Status;
    663 }
    664 
    665 
    666