Home | History | Annotate | Download | only in Udp4Dxe
      1 /** @file
      2 
      3 Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 **/
     13 
     14 
     15 #include "Udp4Impl.h"
     16 
     17 EFI_DRIVER_BINDING_PROTOCOL gUdp4DriverBinding = {
     18   Udp4DriverBindingSupported,
     19   Udp4DriverBindingStart,
     20   Udp4DriverBindingStop,
     21   0xa,
     22   NULL,
     23   NULL
     24 };
     25 
     26 EFI_SERVICE_BINDING_PROTOCOL mUdp4ServiceBinding = {
     27   Udp4ServiceBindingCreateChild,
     28   Udp4ServiceBindingDestroyChild
     29 };
     30 
     31 /**
     32   Callback function which provided by user to remove one node in NetDestroyLinkList process.
     33 
     34   @param[in]    Entry           The entry to be removed.
     35   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
     36 
     37   @retval EFI_SUCCESS           The entry has been removed successfully.
     38   @retval Others                Fail to remove the entry.
     39 
     40 **/
     41 EFI_STATUS
     42 EFIAPI
     43 Udp4DestroyChildEntryInHandleBuffer (
     44   IN LIST_ENTRY         *Entry,
     45   IN VOID               *Context
     46   )
     47 {
     48   UDP4_INSTANCE_DATA            *Instance;
     49   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
     50   UINTN                         NumberOfChildren;
     51   EFI_HANDLE                    *ChildHandleBuffer;
     52 
     53   if (Entry == NULL || Context == NULL) {
     54     return EFI_INVALID_PARAMETER;
     55   }
     56 
     57   Instance = NET_LIST_USER_STRUCT_S (Entry, UDP4_INSTANCE_DATA, Link, UDP4_INSTANCE_DATA_SIGNATURE);
     58   ServiceBinding    = ((UDP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
     59   NumberOfChildren  = ((UDP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
     60   ChildHandleBuffer = ((UDP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
     61 
     62   if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
     63     return EFI_SUCCESS;
     64   }
     65 
     66   return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
     67 }
     68 
     69 
     70 /**
     71   Test to see if this driver supports ControllerHandle. This service
     72   is called by the EFI boot service ConnectController(). In
     73   order to make drivers as small as possible, there are a few calling
     74   restrictions for this service. ConnectController() must
     75   follow these calling restrictions. If any other agent wishes to call
     76   Supported() it must also follow these calling restrictions.
     77 
     78   @param[in]  This                Protocol instance pointer.
     79   @param[in]  ControllerHandle    Handle of device to test
     80   @param[in]  RemainingDevicePath Optional parameter use to pick a specific child
     81                                   device to start.
     82 
     83   @retval EFI_SUCCESS         This driver supports this device
     84   @retval EFI_ALREADY_STARTED This driver is already running on this device
     85   @retval other               This driver does not support this device
     86 
     87 **/
     88 EFI_STATUS
     89 EFIAPI
     90 Udp4DriverBindingSupported (
     91   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
     92   IN EFI_HANDLE                   ControllerHandle,
     93   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath  OPTIONAL
     94   )
     95 {
     96   EFI_STATUS  Status;
     97 
     98   //
     99   // Test for the Udp4ServiceBinding Protocol
    100   //
    101   Status = gBS->OpenProtocol (
    102                   ControllerHandle,
    103                   &gEfiUdp4ServiceBindingProtocolGuid,
    104                   NULL,
    105                   This->DriverBindingHandle,
    106                   ControllerHandle,
    107                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    108                   );
    109   if (!EFI_ERROR (Status)) {
    110     return EFI_ALREADY_STARTED;
    111   }
    112 
    113   //
    114   // Test for the Ip4 Protocol
    115   //
    116   Status = gBS->OpenProtocol (
    117                   ControllerHandle,
    118                   &gEfiIp4ServiceBindingProtocolGuid,
    119                   NULL,
    120                   This->DriverBindingHandle,
    121                   ControllerHandle,
    122                   EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    123                   );
    124 
    125   return Status;
    126 }
    127 
    128 
    129 /**
    130   Start this driver on ControllerHandle. This service is called by the
    131   EFI boot service ConnectController(). In order to make
    132   drivers as small as possible, there are a few calling restrictions for
    133   this service. ConnectController() must follow these
    134   calling restrictions. If any other agent wishes to call Start() it
    135   must also follow these calling restrictions.
    136 
    137   @param[in]  This                 Protocol instance pointer.
    138   @param[in]  ControllerHandle     Handle of device to bind driver to
    139   @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child
    140                                    device to start.
    141 
    142   @retval EFI_SUCCESS          This driver is added to ControllerHandle
    143   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle
    144   @retval other                This driver does not support this device
    145 
    146 **/
    147 EFI_STATUS
    148 EFIAPI
    149 Udp4DriverBindingStart (
    150   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    151   IN EFI_HANDLE                   ControllerHandle,
    152   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath  OPTIONAL
    153   )
    154 {
    155   EFI_STATUS         Status;
    156   UDP4_SERVICE_DATA  *Udp4Service;
    157 
    158   //
    159   // Allocate Private Context Data Structure.
    160   //
    161   Udp4Service = AllocatePool (sizeof (UDP4_SERVICE_DATA));
    162   if (Udp4Service == NULL) {
    163     return EFI_OUT_OF_RESOURCES;
    164   }
    165 
    166   Status = Udp4CreateService (Udp4Service, This->DriverBindingHandle, ControllerHandle);
    167   if (EFI_ERROR (Status)) {
    168     FreePool (Udp4Service);
    169     return Status;
    170   }
    171 
    172   //
    173   // Install the Udp4ServiceBindingProtocol on the ControllerHandle.
    174   //
    175   Status = gBS->InstallMultipleProtocolInterfaces (
    176                   &ControllerHandle,
    177                   &gEfiUdp4ServiceBindingProtocolGuid,
    178                   &Udp4Service->ServiceBinding,
    179                   NULL
    180                   );
    181   if (EFI_ERROR (Status)) {
    182     Udp4CleanService (Udp4Service);
    183     FreePool (Udp4Service);
    184   }
    185 
    186   return Status;
    187 }
    188 
    189 
    190 /**
    191   Stop this driver on ControllerHandle. This service is called by the
    192   EFI boot service DisconnectController(). In order to
    193   make drivers as small as possible, there are a few calling
    194   restrictions for this service. DisconnectController()
    195   must follow these calling restrictions. If any other agent wishes
    196   to call Stop() it must also follow these calling restrictions.
    197 
    198   @param[in]  This              Protocol instance pointer.
    199   @param[in]  ControllerHandle  Handle of device to stop driver on
    200   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    201                                 children is zero stop the entire bus driver.
    202   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
    203 
    204   @retval EFI_SUCCESS       This driver is removed ControllerHandle
    205   @retval other             This driver was not removed from this device
    206 
    207 **/
    208 EFI_STATUS
    209 EFIAPI
    210 Udp4DriverBindingStop (
    211   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
    212   IN  EFI_HANDLE                   ControllerHandle,
    213   IN  UINTN                        NumberOfChildren,
    214   IN  EFI_HANDLE                   *ChildHandleBuffer
    215   )
    216 {
    217   EFI_STATUS                                Status;
    218   EFI_HANDLE                                NicHandle;
    219   EFI_SERVICE_BINDING_PROTOCOL              *ServiceBinding;
    220   UDP4_SERVICE_DATA                         *Udp4Service;
    221   UDP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT  Context;
    222   LIST_ENTRY                                *List;
    223 
    224   //
    225   // Find the NicHandle where UDP4 ServiceBinding Protocol is installed.
    226   //
    227   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
    228   if (NicHandle == NULL) {
    229     return EFI_SUCCESS;
    230   }
    231 
    232   //
    233   // Retrieve the UDP4 ServiceBinding Protocol.
    234   //
    235   Status = gBS->OpenProtocol (
    236                   NicHandle,
    237                   &gEfiUdp4ServiceBindingProtocolGuid,
    238                   (VOID **) &ServiceBinding,
    239                   This->DriverBindingHandle,
    240                   NicHandle,
    241                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    242                   );
    243   if (EFI_ERROR (Status)) {
    244     return EFI_DEVICE_ERROR;
    245   }
    246 
    247   Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (ServiceBinding);
    248   if (NumberOfChildren != 0) {
    249     //
    250     // NumberOfChildren is not zero, destroy the children instances in ChildHandleBuffer.
    251     //
    252     List = &Udp4Service->ChildrenList;
    253     Context.ServiceBinding    = ServiceBinding;
    254     Context.NumberOfChildren  = NumberOfChildren;
    255     Context.ChildHandleBuffer = ChildHandleBuffer;
    256     Status = NetDestroyLinkList (
    257                List,
    258                Udp4DestroyChildEntryInHandleBuffer,
    259                &Context,
    260                NULL
    261                );
    262   } else {
    263     gBS->UninstallMultipleProtocolInterfaces (
    264            NicHandle,
    265            &gEfiUdp4ServiceBindingProtocolGuid,
    266            &Udp4Service->ServiceBinding,
    267            NULL
    268            );
    269 
    270     Udp4CleanService (Udp4Service);
    271 
    272     if (gUdpControllerNameTable != NULL) {
    273       FreeUnicodeStringTable (gUdpControllerNameTable);
    274       gUdpControllerNameTable = NULL;
    275     }
    276     FreePool (Udp4Service);
    277   }
    278 
    279   return Status;
    280 }
    281 
    282 
    283 /**
    284   Creates a child handle and installs a protocol.
    285 
    286   The CreateChild() function installs a protocol on ChildHandle.
    287   If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
    288   If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
    289 
    290   @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
    291   @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
    292                          then a new handle is created. If it is a pointer to an existing UEFI handle,
    293                          then the protocol is added to the existing UEFI handle.
    294 
    295   @retval EFI_SUCCES            The protocol was added to ChildHandle.
    296   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
    297   @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create
    298                                 the child
    299   @retval other                 The child handle was not created
    300 
    301 **/
    302 EFI_STATUS
    303 EFIAPI
    304 Udp4ServiceBindingCreateChild (
    305   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
    306   IN EFI_HANDLE                    *ChildHandle
    307   )
    308 {
    309   EFI_STATUS          Status;
    310   UDP4_SERVICE_DATA   *Udp4Service;
    311   UDP4_INSTANCE_DATA  *Instance;
    312   EFI_TPL             OldTpl;
    313   VOID                *Ip4;
    314 
    315   if ((This == NULL) || (ChildHandle == NULL)) {
    316     return EFI_INVALID_PARAMETER;
    317   }
    318 
    319   Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (This);
    320 
    321   //
    322   // Allocate the instance private data structure.
    323   //
    324   Instance = AllocateZeroPool (sizeof (UDP4_INSTANCE_DATA));
    325   if (Instance == NULL) {
    326     return EFI_OUT_OF_RESOURCES;
    327   }
    328 
    329   Udp4InitInstance (Udp4Service, Instance);
    330 
    331   //
    332   // Add an IpInfo for this instance.
    333   //
    334   Instance->IpInfo = IpIoAddIp (Udp4Service->IpIo);
    335   if (Instance->IpInfo == NULL) {
    336     Status = EFI_OUT_OF_RESOURCES;
    337     goto ON_ERROR;
    338   }
    339 
    340   //
    341   // Install the Udp4Protocol for this instance.
    342   //
    343   Status = gBS->InstallMultipleProtocolInterfaces (
    344                   ChildHandle,
    345                   &gEfiUdp4ProtocolGuid,
    346                   &Instance->Udp4Proto,
    347                   NULL
    348                   );
    349   if (EFI_ERROR (Status)) {
    350     goto ON_ERROR;
    351   }
    352 
    353   Instance->ChildHandle = *ChildHandle;
    354 
    355   //
    356   // Open the default Ip4 protocol in the IP_IO BY_CHILD.
    357   //
    358   Status = gBS->OpenProtocol (
    359                   Udp4Service->IpIo->ChildHandle,
    360                   &gEfiIp4ProtocolGuid,
    361                   (VOID **) &Ip4,
    362                   gUdp4DriverBinding.DriverBindingHandle,
    363                   Instance->ChildHandle,
    364                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    365                   );
    366   if (EFI_ERROR (Status)) {
    367     goto ON_ERROR;
    368   }
    369 
    370   //
    371   // Open this instance's Ip4 protocol in the IpInfo BY_CHILD.
    372   //
    373   Status = gBS->OpenProtocol (
    374                   Instance->IpInfo->ChildHandle,
    375                   &gEfiIp4ProtocolGuid,
    376                   (VOID **) &Ip4,
    377                   gUdp4DriverBinding.DriverBindingHandle,
    378                   Instance->ChildHandle,
    379                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
    380                   );
    381   if (EFI_ERROR (Status)) {
    382     goto ON_ERROR;
    383   }
    384 
    385   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    386 
    387   //
    388   // Link this instance into the service context data and increase the ChildrenNumber.
    389   //
    390   InsertTailList (&Udp4Service->ChildrenList, &Instance->Link);
    391   Udp4Service->ChildrenNumber++;
    392 
    393   gBS->RestoreTPL (OldTpl);
    394 
    395   return EFI_SUCCESS;
    396 
    397 ON_ERROR:
    398 
    399   if (Instance->ChildHandle != NULL) {
    400     gBS->UninstallMultipleProtocolInterfaces (
    401            Instance->ChildHandle,
    402            &gEfiUdp4ProtocolGuid,
    403            &Instance->Udp4Proto,
    404            NULL
    405            );
    406   }
    407 
    408   if (Instance->IpInfo != NULL) {
    409     IpIoRemoveIp (Udp4Service->IpIo, Instance->IpInfo);
    410   }
    411 
    412   Udp4CleanInstance (Instance);
    413 
    414   FreePool (Instance);
    415 
    416   return Status;
    417 }
    418 
    419 
    420 /**
    421   Destroys a child handle with a protocol installed on it.
    422 
    423   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
    424   that was installed by CreateChild() from ChildHandle. If the removed protocol is the
    425   last protocol on ChildHandle, then ChildHandle is destroyed.
    426 
    427   @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
    428   @param[in] ChildHandle Handle of the child to destroy
    429 
    430   @retval EFI_SUCCES            The protocol was removed from ChildHandle.
    431   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
    432   @retval EFI_INVALID_PARAMETER Child handle is NULL.
    433   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
    434                                 because its services are being used.
    435   @retval other                 The child handle was not destroyed
    436 
    437 **/
    438 EFI_STATUS
    439 EFIAPI
    440 Udp4ServiceBindingDestroyChild (
    441   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
    442   IN EFI_HANDLE                    ChildHandle
    443   )
    444 {
    445   EFI_STATUS          Status;
    446   UDP4_SERVICE_DATA   *Udp4Service;
    447   EFI_UDP4_PROTOCOL   *Udp4Proto;
    448   UDP4_INSTANCE_DATA  *Instance;
    449   EFI_TPL             OldTpl;
    450 
    451   if ((This == NULL) || (ChildHandle == NULL)) {
    452     return EFI_INVALID_PARAMETER;
    453   }
    454 
    455   Udp4Service = UDP4_SERVICE_DATA_FROM_THIS (This);
    456 
    457   //
    458   // Try to get the Udp4 protocol from the ChildHandle.
    459   //
    460   Status = gBS->OpenProtocol (
    461                   ChildHandle,
    462                   &gEfiUdp4ProtocolGuid,
    463                   (VOID **) &Udp4Proto,
    464                   gUdp4DriverBinding.DriverBindingHandle,
    465                   ChildHandle,
    466                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    467                   );
    468   if (EFI_ERROR (Status)) {
    469     return EFI_UNSUPPORTED;
    470   }
    471 
    472   Instance = UDP4_INSTANCE_DATA_FROM_THIS (Udp4Proto);
    473 
    474   if (Instance->InDestroy) {
    475     return EFI_SUCCESS;
    476   }
    477 
    478   //
    479   // Use the Destroyed flag to avoid the re-entering of the following code.
    480   //
    481   Instance->InDestroy = TRUE;
    482 
    483   //
    484   // Close the Ip4 protocol.
    485   //
    486   gBS->CloseProtocol (
    487          Udp4Service->IpIo->ChildHandle,
    488          &gEfiIp4ProtocolGuid,
    489          gUdp4DriverBinding.DriverBindingHandle,
    490          Instance->ChildHandle
    491          );
    492   //
    493   // Close the Ip4 protocol on this instance's IpInfo.
    494   //
    495   gBS->CloseProtocol (
    496          Instance->IpInfo->ChildHandle,
    497          &gEfiIp4ProtocolGuid,
    498          gUdp4DriverBinding.DriverBindingHandle,
    499          Instance->ChildHandle
    500          );
    501 
    502   //
    503   // Uninstall the Udp4Protocol previously installed on the ChildHandle.
    504   //
    505   Status = gBS->UninstallMultipleProtocolInterfaces (
    506                   ChildHandle,
    507                   &gEfiUdp4ProtocolGuid,
    508                   (VOID *) &Instance->Udp4Proto,
    509                   NULL
    510                   );
    511   if (EFI_ERROR (Status)) {
    512     Instance->InDestroy = FALSE;
    513     return Status;
    514   }
    515 
    516   //
    517   // Reset the configuration in case the instance's consumer forgets to do this.
    518   //
    519   Udp4Proto->Configure (Udp4Proto, NULL);
    520 
    521   //
    522   // Remove the IpInfo this instance consumes.
    523   //
    524   IpIoRemoveIp (Udp4Service->IpIo, Instance->IpInfo);
    525 
    526   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    527 
    528   //
    529   // Remove this instance from the service context data's ChildrenList.
    530   //
    531   RemoveEntryList (&Instance->Link);
    532   Udp4Service->ChildrenNumber--;
    533 
    534   //
    535   // Clean the instance.
    536   //
    537   Udp4CleanInstance (Instance);
    538 
    539   gBS->RestoreTPL (OldTpl);
    540 
    541   FreePool (Instance);
    542 
    543   return EFI_SUCCESS;
    544 }
    545 
    546 /**
    547   This is the declaration of an EFI image entry point. This entry point is
    548   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
    549   both device drivers and bus drivers.
    550 
    551   The entry point for Udp4 driver which installs the driver binding
    552   and component name protocol on its ImageHandle.
    553 
    554   @param[in] ImageHandle           The firmware allocated handle for the UEFI image.
    555   @param[in] SystemTable           A pointer to the EFI System Table.
    556 
    557   @retval EFI_SUCCESS           The operation completed successfully.
    558   @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
    559 
    560 **/
    561 EFI_STATUS
    562 EFIAPI
    563 Udp4DriverEntryPoint (
    564   IN EFI_HANDLE        ImageHandle,
    565   IN EFI_SYSTEM_TABLE  *SystemTable
    566   )
    567 {
    568   EFI_STATUS  Status;
    569 
    570   //
    571   // Install the Udp4DriverBinding and Udp4ComponentName protocols.
    572   //
    573   Status = EfiLibInstallDriverBindingComponentName2 (
    574              ImageHandle,
    575              SystemTable,
    576              &gUdp4DriverBinding,
    577              ImageHandle,
    578              &gUdp4ComponentName,
    579              &gUdp4ComponentName2
    580              );
    581   if (!EFI_ERROR (Status)) {
    582     //
    583     // Initialize the UDP random port.
    584     //
    585     mUdp4RandomPort = (UINT16) (((UINT16) NetRandomInitSeed ()) % UDP4_PORT_KNOWN + UDP4_PORT_KNOWN);
    586   }
    587 
    588   return Status;
    589 }
    590 
    591