Home | History | Annotate | Download | only in HttpDxe
      1 /** @file
      2   The driver binding and service binding protocol for HttpDxe driver.
      3 
      4   Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
      5 
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php.
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "HttpDriver.h"
     17 
     18 EFI_HTTP_UTILITIES_PROTOCOL *mHttpUtilities = NULL;
     19 
     20 ///
     21 /// Driver Binding Protocol instance
     22 ///
     23 EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp4DriverBinding = {
     24   HttpDxeIp4DriverBindingSupported,
     25   HttpDxeIp4DriverBindingStart,
     26   HttpDxeIp4DriverBindingStop,
     27   HTTP_DRIVER_VERSION,
     28   NULL,
     29   NULL
     30 };
     31 
     32 EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp6DriverBinding = {
     33   HttpDxeIp6DriverBindingSupported,
     34   HttpDxeIp6DriverBindingStart,
     35   HttpDxeIp6DriverBindingStop,
     36   HTTP_DRIVER_VERSION,
     37   NULL,
     38   NULL
     39 };
     40 
     41 
     42 /**
     43   Create a HTTP driver service binding private instance.
     44 
     45   @param[in]  Controller         The controller that has TCP4 service binding
     46                                  installed.
     47   @param[in]  ImageHandle        The HTTP driver's image handle.
     48   @param[out] ServiceData        Point to HTTP driver private instance.
     49 
     50   @retval EFI_OUT_OF_RESOURCES   Failed to allocate some resources.
     51   @retval EFI_SUCCESS            A new HTTP driver private instance is created.
     52 
     53 **/
     54 EFI_STATUS
     55 HttpCreateService (
     56   IN  EFI_HANDLE            Controller,
     57   IN  EFI_HANDLE            ImageHandle,
     58   OUT HTTP_SERVICE          **ServiceData
     59   )
     60 {
     61   HTTP_SERVICE     *HttpService;
     62 
     63   ASSERT (ServiceData != NULL);
     64   *ServiceData = NULL;
     65 
     66   HttpService = AllocateZeroPool (sizeof (HTTP_SERVICE));
     67   if (HttpService == NULL) {
     68     return EFI_OUT_OF_RESOURCES;
     69   }
     70 
     71   HttpService->Signature = HTTP_SERVICE_SIGNATURE;
     72   HttpService->ServiceBinding.CreateChild = HttpServiceBindingCreateChild;
     73   HttpService->ServiceBinding.DestroyChild = HttpServiceBindingDestroyChild;
     74   HttpService->ImageHandle = ImageHandle;
     75   HttpService->ControllerHandle = Controller;
     76   HttpService->ChildrenNumber = 0;
     77   InitializeListHead (&HttpService->ChildrenList);
     78 
     79   *ServiceData = HttpService;
     80   return EFI_SUCCESS;
     81 }
     82 
     83 /**
     84   Release all the resource used the HTTP service binding instance.
     85 
     86   @param[in]  HttpService        The HTTP private instance.
     87   @param[in]  UsingIpv6          Indicate use TCP4 protocol or TCP6 protocol.
     88                                  if TRUE, use Tcp6 protocol.
     89                                  if FALSE, use Tcp4 protocl.
     90 **/
     91 VOID
     92 HttpCleanService (
     93   IN HTTP_SERVICE     *HttpService,
     94   IN BOOLEAN          UsingIpv6
     95   )
     96 {
     97 
     98   if (HttpService == NULL) {
     99     return ;
    100   }
    101   if (!UsingIpv6) {
    102     if (HttpService->Tcp4ChildHandle != NULL) {
    103       gBS->CloseProtocol (
    104              HttpService->Tcp4ChildHandle,
    105              &gEfiTcp4ProtocolGuid,
    106              HttpService->ImageHandle,
    107              HttpService->ControllerHandle
    108              );
    109 
    110       NetLibDestroyServiceChild (
    111         HttpService->ControllerHandle,
    112         HttpService->ImageHandle,
    113         &gEfiTcp4ServiceBindingProtocolGuid,
    114         HttpService->Tcp4ChildHandle
    115         );
    116 
    117       HttpService->Tcp4ChildHandle = NULL;
    118     }
    119   } else {
    120     if (HttpService->Tcp6ChildHandle != NULL) {
    121       gBS->CloseProtocol (
    122              HttpService->Tcp6ChildHandle,
    123              &gEfiTcp6ProtocolGuid,
    124              HttpService->ImageHandle,
    125              HttpService->ControllerHandle
    126              );
    127 
    128       NetLibDestroyServiceChild (
    129         HttpService->ControllerHandle,
    130         HttpService->ImageHandle,
    131         &gEfiTcp6ServiceBindingProtocolGuid,
    132         HttpService->Tcp6ChildHandle
    133         );
    134 
    135       HttpService->Tcp6ChildHandle = NULL;
    136     }
    137   }
    138 
    139 }
    140 
    141 /**
    142   The event process routine when the http utilities protocol is installed
    143   in the system.
    144 
    145   @param[in]     Event         Not used.
    146   @param[in]     Context       The pointer to the IP4 config2 instance data or IP6 Config instance data.
    147 
    148 **/
    149 VOID
    150 EFIAPI
    151 HttpUtilitiesInstalledCallback (
    152   IN EFI_EVENT  Event,
    153   IN VOID       *Context
    154   )
    155 {
    156   gBS->LocateProtocol (
    157          &gEfiHttpUtilitiesProtocolGuid,
    158          NULL,
    159          (VOID **) &mHttpUtilities
    160          );
    161 
    162   //
    163   // Close the event if Http utilities protocol is loacted.
    164   //
    165   if (mHttpUtilities != NULL && Event != NULL) {
    166      gBS->CloseEvent (Event);
    167   }
    168 }
    169 
    170 /**
    171   This is the declaration of an EFI image entry point. This entry point is
    172   the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
    173   both device drivers and bus drivers.
    174 
    175   @param  ImageHandle           The firmware allocated handle for the UEFI image.
    176   @param  SystemTable           A pointer to the EFI System Table.
    177 
    178   @retval EFI_SUCCESS           The operation completed successfully.
    179   @retval Others                An unexpected error occurred.
    180 
    181 **/
    182 EFI_STATUS
    183 EFIAPI
    184 HttpDxeDriverEntryPoint (
    185   IN EFI_HANDLE        ImageHandle,
    186   IN EFI_SYSTEM_TABLE  *SystemTable
    187   )
    188 {
    189   EFI_STATUS     Status;
    190   VOID           *Registration;
    191 
    192   gBS->LocateProtocol (
    193          &gEfiHttpUtilitiesProtocolGuid,
    194          NULL,
    195          (VOID **) &mHttpUtilities
    196          );
    197 
    198   if (mHttpUtilities == NULL) {
    199     //
    200     // No Http utilities protocol, register a notify.
    201     //
    202     EfiCreateProtocolNotifyEvent (
    203       &gEfiHttpUtilitiesProtocolGuid,
    204       TPL_CALLBACK,
    205       HttpUtilitiesInstalledCallback,
    206       NULL,
    207       &Registration
    208       );
    209   }
    210 
    211   //
    212   // Install UEFI Driver Model protocol(s).
    213   //
    214   Status = EfiLibInstallDriverBindingComponentName2 (
    215              ImageHandle,
    216              SystemTable,
    217              &gHttpDxeIp4DriverBinding,
    218              ImageHandle,
    219              &gHttpDxeComponentName,
    220              &gHttpDxeComponentName2
    221              );
    222   if (EFI_ERROR (Status)) {
    223     return Status;
    224   }
    225 
    226   Status = EfiLibInstallDriverBindingComponentName2 (
    227              ImageHandle,
    228              SystemTable,
    229              &gHttpDxeIp6DriverBinding,
    230              NULL,
    231              &gHttpDxeComponentName,
    232              &gHttpDxeComponentName2
    233              );
    234   if (EFI_ERROR (Status)) {
    235     gBS->UninstallMultipleProtocolInterfaces (
    236            ImageHandle,
    237            &gEfiDriverBindingProtocolGuid,
    238            &gHttpDxeIp4DriverBinding,
    239            &gEfiComponentName2ProtocolGuid,
    240            &gHttpDxeComponentName2,
    241            &gEfiComponentNameProtocolGuid,
    242            &gHttpDxeComponentName,
    243            NULL
    244            );
    245   }
    246   return Status;
    247 }
    248 
    249 /**
    250   Callback function which provided by user to remove one node in NetDestroyLinkList process.
    251 
    252   @param[in]    Entry           The entry to be removed.
    253   @param[in]    Context         Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
    254 
    255   @retval EFI_INVALID_PARAMETER Any input parameter is NULL.
    256   @retval EFI_SUCCESS           The entry has been removed successfully.
    257   @retval Others                Fail to remove the entry.
    258 
    259 **/
    260 EFI_STATUS
    261 EFIAPI
    262 HttpDestroyChildEntryInHandleBuffer (
    263   IN LIST_ENTRY         *Entry,
    264   IN VOID               *Context
    265   )
    266 {
    267   HTTP_PROTOCOL                 *HttpInstance;
    268   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;
    269   UINTN                         NumberOfChildren;
    270   EFI_HANDLE                    *ChildHandleBuffer;
    271 
    272   if (Entry == NULL || Context == NULL) {
    273     return EFI_INVALID_PARAMETER;
    274   }
    275 
    276   HttpInstance = NET_LIST_USER_STRUCT_S (Entry, HTTP_PROTOCOL, Link, HTTP_PROTOCOL_SIGNATURE);
    277   ServiceBinding    = ((HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
    278   NumberOfChildren  = ((HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
    279   ChildHandleBuffer = ((HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
    280 
    281   if (!NetIsInHandleBuffer (HttpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {
    282     return EFI_SUCCESS;
    283   }
    284 
    285   return ServiceBinding->DestroyChild (ServiceBinding, HttpInstance->Handle);
    286 }
    287 
    288 /**
    289   Test to see if this driver supports ControllerHandle. This is the worker function for
    290   HttpDxeIp4(6)DriverBindingSupported.
    291 
    292   @param[in]  This                The pointer to the driver binding protocol.
    293   @param[in]  ControllerHandle    The handle of device to be tested.
    294   @param[in]  RemainingDevicePath Optional parameter used to pick a specific child
    295                                   device to be started.
    296   @param[in]  IpVersion           IP_VERSION_4 or IP_VERSION_6.
    297 
    298   @retval EFI_SUCCESS         This driver supports this device.
    299   @retval EFI_UNSUPPORTED     This driver does not support this device.
    300 
    301 **/
    302 EFI_STATUS
    303 EFIAPI
    304 HttpDxeSupported (
    305   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    306   IN EFI_HANDLE                   ControllerHandle,
    307   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
    308   IN UINT8                        IpVersion
    309   )
    310 {
    311   EFI_STATUS                      Status;
    312   EFI_GUID                        *TcpServiceBindingProtocolGuid;
    313 
    314   if (IpVersion == IP_VERSION_4) {
    315     TcpServiceBindingProtocolGuid = &gEfiTcp4ServiceBindingProtocolGuid;
    316   } else {
    317     TcpServiceBindingProtocolGuid = &gEfiTcp6ServiceBindingProtocolGuid;
    318   }
    319 
    320   Status = gBS->OpenProtocol (
    321                 ControllerHandle,
    322                 TcpServiceBindingProtocolGuid,
    323                 NULL,
    324                 This->DriverBindingHandle,
    325                 ControllerHandle,
    326                 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    327                 );
    328 
    329   if (EFI_ERROR (Status)) {
    330     return EFI_UNSUPPORTED;
    331   }
    332 
    333   return EFI_SUCCESS;
    334 }
    335 
    336 /**
    337   Start this driver on ControllerHandle. This is the worker function for
    338   HttpDxeIp4(6)DriverBindingStart.
    339 
    340   @param[in]  This                 The pointer to the driver binding protocol.
    341   @param[in]  ControllerHandle     The handle of device to be started.
    342   @param[in]  RemainingDevicePath  Optional parameter used to pick a specific child
    343                                    device to be started.
    344   @param[in]  IpVersion            IP_VERSION_4 or IP_VERSION_6.
    345 
    346 
    347   @retval EFI_SUCCESS          This driver is installed to ControllerHandle.
    348   @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle.
    349   @retval other                This driver does not support this device.
    350 
    351 **/
    352 EFI_STATUS
    353 EFIAPI
    354 HttpDxeStart (
    355   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    356   IN EFI_HANDLE                   ControllerHandle,
    357   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL,
    358   IN UINT8                        IpVersion
    359   )
    360 {
    361   EFI_STATUS                      Status;
    362   EFI_SERVICE_BINDING_PROTOCOL    *ServiceBinding;
    363   HTTP_SERVICE                    *HttpService;
    364   VOID                            *Interface;
    365   BOOLEAN                         UsingIpv6;
    366 
    367   UsingIpv6 = FALSE;
    368 
    369   //
    370   // Test for the Http service binding protocol
    371   //
    372   Status = gBS->OpenProtocol (
    373                   ControllerHandle,
    374                   &gEfiHttpServiceBindingProtocolGuid,
    375                   (VOID **) &ServiceBinding,
    376                   This->DriverBindingHandle,
    377                   ControllerHandle,
    378                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    379                   );
    380 
    381   if (!EFI_ERROR (Status)) {
    382     HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);
    383   } else {
    384     Status = HttpCreateService (ControllerHandle, This->DriverBindingHandle, &HttpService);
    385     if (EFI_ERROR (Status)) {
    386       return Status;
    387     }
    388 
    389     ASSERT (HttpService != NULL);
    390 
    391     //
    392     // Install the HttpServiceBinding Protocol onto Controller
    393     //
    394     Status = gBS->InstallMultipleProtocolInterfaces (
    395                     &ControllerHandle,
    396                     &gEfiHttpServiceBindingProtocolGuid,
    397                     &HttpService->ServiceBinding,
    398                     NULL
    399                     );
    400 
    401     if (EFI_ERROR (Status)) {
    402       goto ON_ERROR;
    403     }
    404   }
    405 
    406   if (IpVersion == IP_VERSION_4) {
    407 
    408     if (HttpService->Tcp4ChildHandle == NULL) {
    409       //
    410       // Create a TCP4 child instance, but do not configure it. This will establish the parent-child relationship.
    411       //
    412       Status = NetLibCreateServiceChild (
    413                  ControllerHandle,
    414                  This->DriverBindingHandle,
    415                  &gEfiTcp4ServiceBindingProtocolGuid,
    416                  &HttpService->Tcp4ChildHandle
    417                  );
    418 
    419       if (EFI_ERROR (Status)) {
    420         goto ON_ERROR;
    421       }
    422 
    423       Status = gBS->OpenProtocol (
    424                       HttpService->Tcp4ChildHandle,
    425                       &gEfiTcp4ProtocolGuid,
    426                       &Interface,
    427                       This->DriverBindingHandle,
    428                       ControllerHandle,
    429                       EFI_OPEN_PROTOCOL_BY_DRIVER
    430                       );
    431 
    432       if (EFI_ERROR (Status)) {
    433         goto ON_ERROR;
    434       }
    435 
    436     } else {
    437       return EFI_ALREADY_STARTED;
    438     }
    439 
    440   } else {
    441     UsingIpv6 = TRUE;
    442 
    443     if (HttpService->Tcp6ChildHandle == NULL) {
    444       //
    445       // Create a TCP6 child instance, but do not configure it. This will establish the parent-child relationship.
    446       //
    447       Status = NetLibCreateServiceChild (
    448                  ControllerHandle,
    449                  This->DriverBindingHandle,
    450                  &gEfiTcp6ServiceBindingProtocolGuid,
    451                  &HttpService->Tcp6ChildHandle
    452                  );
    453 
    454       if (EFI_ERROR (Status)) {
    455         goto ON_ERROR;
    456       }
    457 
    458       Status = gBS->OpenProtocol (
    459                       HttpService->Tcp6ChildHandle,
    460                       &gEfiTcp6ProtocolGuid,
    461                       &Interface,
    462                       This->DriverBindingHandle,
    463                       ControllerHandle,
    464                       EFI_OPEN_PROTOCOL_BY_DRIVER
    465                       );
    466 
    467       if (EFI_ERROR (Status)) {
    468         goto ON_ERROR;
    469       }
    470 
    471     } else {
    472       return EFI_ALREADY_STARTED;
    473     }
    474 
    475   }
    476 
    477   return EFI_SUCCESS;
    478 
    479 ON_ERROR:
    480 
    481   if (HttpService != NULL) {
    482     HttpCleanService (HttpService, UsingIpv6);
    483     if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {
    484       FreePool (HttpService);
    485     }
    486   }
    487 
    488   return Status;
    489 
    490 
    491 }
    492 
    493 /**
    494   Stop this driver on ControllerHandle. This is the worker function for
    495   HttpDxeIp4(6)DriverBindingStop.
    496 
    497   @param[in]  This              Protocol instance pointer.
    498   @param[in]  ControllerHandle  Handle of device to stop driver on.
    499   @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of
    500                                 children is zero stop the entire bus driver.
    501   @param[in]  ChildHandleBuffer List of Child Handles to Stop.
    502   @param[in]  IpVersion         IP_VERSION_4 or IP_VERSION_6.
    503 
    504   @retval EFI_SUCCESS           This driver was removed ControllerHandle.
    505   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
    506   @retval Others                This driver was not removed from this device
    507 
    508 **/
    509 EFI_STATUS
    510 EFIAPI
    511 HttpDxeStop (
    512   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    513   IN EFI_HANDLE                   ControllerHandle,
    514   IN UINTN                        NumberOfChildren,
    515   IN EFI_HANDLE                   *ChildHandleBuffer,
    516   IN UINT8                        IpVersion
    517   )
    518 {
    519   EFI_HANDLE                                 NicHandle;
    520   EFI_STATUS                                 Status;
    521   EFI_SERVICE_BINDING_PROTOCOL               *ServiceBinding;
    522   HTTP_SERVICE                               *HttpService;
    523   LIST_ENTRY                                 *List;
    524   HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT   Context;
    525   BOOLEAN                                    UsingIpv6;
    526 
    527   //
    528   // HTTP driver opens TCP4(6) child, So, Controller is a TCP4(6)
    529   // child handle. Locate the Nic handle first. Then get the
    530   // HTTP private data back.
    531   //
    532   if (IpVersion == IP_VERSION_4) {
    533     UsingIpv6 = FALSE;
    534     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);
    535   } else {
    536     UsingIpv6 = TRUE;
    537     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp6ProtocolGuid);
    538   }
    539 
    540   if (NicHandle == NULL) {
    541     return EFI_SUCCESS;
    542   }
    543 
    544   Status = gBS->OpenProtocol (
    545                   NicHandle,
    546                   &gEfiHttpServiceBindingProtocolGuid,
    547                   (VOID **) &ServiceBinding,
    548                   This->DriverBindingHandle,
    549                   NicHandle,
    550                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    551                   );
    552 
    553   if (!EFI_ERROR (Status)) {
    554 
    555     HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);
    556 
    557     if (NumberOfChildren != 0) {
    558       //
    559       // Destroy the HTTP child instance in ChildHandleBuffer.
    560       //
    561       List = &HttpService->ChildrenList;
    562       Context.ServiceBinding    = ServiceBinding;
    563       Context.NumberOfChildren  = NumberOfChildren;
    564       Context.ChildHandleBuffer = ChildHandleBuffer;
    565       Status = NetDestroyLinkList (
    566                  List,
    567                  HttpDestroyChildEntryInHandleBuffer,
    568                  &Context,
    569                  NULL
    570                  );
    571     } else {
    572 
    573       HttpCleanService (HttpService, UsingIpv6);
    574 
    575       if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {
    576         gBS->UninstallProtocolInterface (
    577                NicHandle,
    578                &gEfiHttpServiceBindingProtocolGuid,
    579                ServiceBinding
    580                );
    581         FreePool (HttpService);
    582       }
    583       Status = EFI_SUCCESS;
    584     }
    585   }
    586 
    587   return Status;
    588 
    589 }
    590 
    591 /**
    592   Tests to see if this driver supports a given controller. If a child device is provided,
    593   it further tests to see if this driver supports creating a handle for the specified child device.
    594 
    595   This function checks to see if the driver specified by This supports the device specified by
    596   ControllerHandle. Drivers will typically use the device path attached to
    597   ControllerHandle and/or the services from the bus I/O abstraction attached to
    598   ControllerHandle to determine if the driver supports ControllerHandle. This function
    599   may be called many times during platform initialization. In order to reduce boot times, the tests
    600   performed by this function must be very small, and take as little time as possible to execute. This
    601   function must not change the state of any hardware devices, and this function must be aware that the
    602   device specified by ControllerHandle may already be managed by the same driver or a
    603   different driver. This function must match its calls to AllocatePages() with FreePages(),
    604   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    605   Because ControllerHandle may have been previously started by the same driver, if a protocol is
    606   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    607   to guarantee the state of ControllerHandle is not modified by this function.
    608 
    609   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    610   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    611                                    must support a protocol interface that supplies
    612                                    an I/O abstraction to the driver.
    613   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    614                                    parameter is ignored by device drivers, and is optional for bus
    615                                    drivers. For bus drivers, if this parameter is not NULL, then
    616                                    the bus driver must determine if the bus controller specified
    617                                    by ControllerHandle and the child controller specified
    618                                    by RemainingDevicePath are both supported by this
    619                                    bus driver.
    620 
    621   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    622                                    RemainingDevicePath is supported by the driver specified by This.
    623   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    624                                    RemainingDevicePath is already being managed by the driver
    625                                    specified by This.
    626   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    627                                    RemainingDevicePath is already being managed by a different
    628                                    driver or an application that requires exclusive access.
    629                                    Currently not implemented.
    630   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    631                                    RemainingDevicePath is not supported by the driver specified by This.
    632 **/
    633 EFI_STATUS
    634 EFIAPI
    635 HttpDxeIp4DriverBindingSupported (
    636   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    637   IN EFI_HANDLE                   ControllerHandle,
    638   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    639   )
    640 {
    641   return HttpDxeSupported (
    642            This,
    643            ControllerHandle,
    644            RemainingDevicePath,
    645            IP_VERSION_4
    646            );
    647 }
    648 
    649 /**
    650   Starts a device controller or a bus controller.
    651 
    652   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    653   As a result, much of the error checking on the parameters to Start() has been moved into this
    654   common boot service. It is legal to call Start() from other locations,
    655   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    656   1. ControllerHandle must be a valid EFI_HANDLE.
    657   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    658      EFI_DEVICE_PATH_PROTOCOL.
    659   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    660      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    661 
    662   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    663   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    664                                    must support a protocol interface that supplies
    665                                    an I/O abstraction to the driver.
    666   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    667                                    parameter is ignored by device drivers, and is optional for bus
    668                                    drivers. For a bus driver, if this parameter is NULL, then handles
    669                                    for all the children of Controller are created by this driver.
    670                                    If this parameter is not NULL and the first Device Path Node is
    671                                    not the End of Device Path Node, then only the handle for the
    672                                    child device specified by the first Device Path Node of
    673                                    RemainingDevicePath is created by this driver.
    674                                    If the first Device Path Node of RemainingDevicePath is
    675                                    the End of Device Path Node, no child handle is created by this
    676                                    driver.
    677 
    678   @retval EFI_SUCCESS              The device was started.
    679   @retval EFI_ALREADY_STARTED      This device is already running on ControllerHandle.
    680   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    681   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    682   @retval Others                   The driver failded to start the device.
    683 
    684 **/
    685 EFI_STATUS
    686 EFIAPI
    687 HttpDxeIp4DriverBindingStart (
    688   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    689   IN EFI_HANDLE                   ControllerHandle,
    690   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    691   )
    692 {
    693   return HttpDxeStart (
    694            This,
    695            ControllerHandle,
    696            RemainingDevicePath,
    697            IP_VERSION_4
    698            );
    699 }
    700 
    701 /**
    702   Stops a device controller or a bus controller.
    703 
    704   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    705   As a result, much of the error checking on the parameters to Stop() has been moved
    706   into this common boot service. It is legal to call Stop() from other locations,
    707   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    708   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    709      same driver's Start() function.
    710   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    711      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    712      Start() function, and the Start() function must have called OpenProtocol() on
    713      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    714 
    715   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    716   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    717                                 support a bus specific I/O protocol for the driver
    718                                 to use to stop the device.
    719   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    720   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    721                                 if NumberOfChildren is 0.
    722 
    723   @retval EFI_SUCCESS           The device was stopped.
    724   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    725 
    726 **/
    727 EFI_STATUS
    728 EFIAPI
    729 HttpDxeIp4DriverBindingStop (
    730   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    731   IN EFI_HANDLE                   ControllerHandle,
    732   IN UINTN                        NumberOfChildren,
    733   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
    734   )
    735 {
    736   return HttpDxeStop (
    737            This,
    738            ControllerHandle,
    739            NumberOfChildren,
    740            ChildHandleBuffer,
    741            IP_VERSION_4
    742            );
    743 }
    744 
    745 /**
    746   Tests to see if this driver supports a given controller. If a child device is provided,
    747   it further tests to see if this driver supports creating a handle for the specified child device.
    748 
    749   This function checks to see if the driver specified by This supports the device specified by
    750   ControllerHandle. Drivers will typically use the device path attached to
    751   ControllerHandle and/or the services from the bus I/O abstraction attached to
    752   ControllerHandle to determine if the driver supports ControllerHandle. This function
    753   may be called many times during platform initialization. In order to reduce boot times, the tests
    754   performed by this function must be very small, and take as little time as possible to execute. This
    755   function must not change the state of any hardware devices, and this function must be aware that the
    756   device specified by ControllerHandle may already be managed by the same driver or a
    757   different driver. This function must match its calls to AllocatePages() with FreePages(),
    758   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    759   Because ControllerHandle may have been previously started by the same driver, if a protocol is
    760   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    761   to guarantee the state of ControllerHandle is not modified by this function.
    762 
    763   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    764   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    765                                    must support a protocol interface that supplies
    766                                    an I/O abstraction to the driver.
    767   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    768                                    parameter is ignored by device drivers, and is optional for bus
    769                                    drivers. For bus drivers, if this parameter is not NULL, then
    770                                    the bus driver must determine if the bus controller specified
    771                                    by ControllerHandle and the child controller specified
    772                                    by RemainingDevicePath are both supported by this
    773                                    bus driver.
    774 
    775   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    776                                    RemainingDevicePath is supported by the driver specified by This.
    777   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    778                                    RemainingDevicePath is already being managed by the driver
    779                                    specified by This.
    780   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    781                                    RemainingDevicePath is already being managed by a different
    782                                    driver or an application that requires exclusive access.
    783                                    Currently not implemented.
    784   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    785                                    RemainingDevicePath is not supported by the driver specified by This.
    786 **/
    787 EFI_STATUS
    788 EFIAPI
    789 HttpDxeIp6DriverBindingSupported (
    790   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    791   IN EFI_HANDLE                   ControllerHandle,
    792   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    793   )
    794 {
    795   return HttpDxeSupported (
    796            This,
    797            ControllerHandle,
    798            RemainingDevicePath,
    799            IP_VERSION_6
    800            );
    801 
    802 }
    803 
    804 /**
    805   Starts a device controller or a bus controller.
    806 
    807   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    808   As a result, much of the error checking on the parameters to Start() has been moved into this
    809   common boot service. It is legal to call Start() from other locations,
    810   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    811   1. ControllerHandle must be a valid EFI_HANDLE.
    812   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    813      EFI_DEVICE_PATH_PROTOCOL.
    814   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    815      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    816 
    817   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    818   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    819                                    must support a protocol interface that supplies
    820                                    an I/O abstraction to the driver.
    821   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    822                                    parameter is ignored by device drivers, and is optional for bus
    823                                    drivers. For a bus driver, if this parameter is NULL, then handles
    824                                    for all the children of Controller are created by this driver.
    825                                    If this parameter is not NULL and the first Device Path Node is
    826                                    not the End of Device Path Node, then only the handle for the
    827                                    child device specified by the first Device Path Node of
    828                                    RemainingDevicePath is created by this driver.
    829                                    If the first Device Path Node of RemainingDevicePath is
    830                                    the End of Device Path Node, no child handle is created by this
    831                                    driver.
    832 
    833   @retval EFI_SUCCESS              The device was started.
    834   @retval EFI_ALREADY_STARTED      This device is already running on ControllerHandle.
    835   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    836   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    837   @retval Others                   The driver failded to start the device.
    838 
    839 **/
    840 EFI_STATUS
    841 EFIAPI
    842 HttpDxeIp6DriverBindingStart (
    843   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    844   IN EFI_HANDLE                   ControllerHandle,
    845   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL
    846   )
    847 {
    848   return HttpDxeStart (
    849            This,
    850            ControllerHandle,
    851            RemainingDevicePath,
    852            IP_VERSION_6
    853            );
    854 }
    855 
    856 /**
    857   Stops a device controller or a bus controller.
    858 
    859   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    860   As a result, much of the error checking on the parameters to Stop() has been moved
    861   into this common boot service. It is legal to call Stop() from other locations,
    862   but the following calling restrictions must be followed, or the system behavior will not be deterministic.
    863   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    864      same driver's Start() function.
    865   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    866      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    867      Start() function, and the Start() function must have called OpenProtocol() on
    868      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    869 
    870   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    871   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    872                                 support a bus specific I/O protocol for the driver
    873                                 to use to stop the device.
    874   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    875   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    876                                 if NumberOfChildren is 0.
    877 
    878   @retval EFI_SUCCESS           The device was stopped.
    879   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    880 
    881 **/
    882 EFI_STATUS
    883 EFIAPI
    884 HttpDxeIp6DriverBindingStop (
    885   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    886   IN EFI_HANDLE                   ControllerHandle,
    887   IN UINTN                        NumberOfChildren,
    888   IN EFI_HANDLE                   *ChildHandleBuffer OPTIONAL
    889   )
    890 {
    891   return HttpDxeStop (
    892            This,
    893            ControllerHandle,
    894            NumberOfChildren,
    895            ChildHandleBuffer,
    896            IP_VERSION_6
    897            );
    898 }
    899 /**
    900   Creates a child handle and installs a protocol.
    901 
    902   The CreateChild() function installs a protocol on ChildHandle.
    903   If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
    904   If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
    905 
    906   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
    907   @param  ChildHandle Pointer to the handle of the child to create. If it is NULL,
    908                       then a new handle is created. If it is a pointer to an existing UEFI handle,
    909                       then the protocol is added to the existing UEFI handle.
    910 
    911   @retval EFI_SUCCES            The protocol was added to ChildHandle.
    912   @retval EFI_INVALID_PARAMETER This is NULL, or ChildHandle is NULL.
    913   @retval EFI_OUT_OF_RESOURCES  There are not enough resources availabe to create
    914                                 the child.
    915   @retval other                 The child handle was not created.
    916 
    917 **/
    918 EFI_STATUS
    919 EFIAPI
    920 HttpServiceBindingCreateChild (
    921   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
    922   IN OUT EFI_HANDLE                *ChildHandle
    923   )
    924 {
    925   HTTP_SERVICE         *HttpService;
    926   HTTP_PROTOCOL        *HttpInstance;
    927   EFI_STATUS           Status;
    928   EFI_TPL              OldTpl;
    929 
    930   if ((This == NULL) || (ChildHandle == NULL)) {
    931     return EFI_INVALID_PARAMETER;
    932   }
    933 
    934   HttpService  = HTTP_SERVICE_FROM_PROTOCOL (This);
    935   HttpInstance = AllocateZeroPool (sizeof (HTTP_PROTOCOL));
    936   if (HttpInstance == NULL) {
    937     return EFI_OUT_OF_RESOURCES;
    938   }
    939 
    940   HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE;
    941   HttpInstance->Service   = HttpService;
    942   CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http));
    943   NetMapInit (&HttpInstance->TxTokens);
    944   NetMapInit (&HttpInstance->RxTokens);
    945 
    946   //
    947   // Install HTTP protocol onto ChildHandle
    948   //
    949   Status = gBS->InstallMultipleProtocolInterfaces (
    950                   ChildHandle,
    951                   &gEfiHttpProtocolGuid,
    952                   &HttpInstance->Http,
    953                   NULL
    954                   );
    955 
    956   if (EFI_ERROR (Status)) {
    957     goto ON_ERROR;
    958   }
    959 
    960   HttpInstance->Handle    = *ChildHandle;
    961 
    962   //
    963   // Add it to the HTTP service's child list.
    964   //
    965   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    966 
    967   InsertTailList (&HttpService->ChildrenList, &HttpInstance->Link);
    968   HttpService->ChildrenNumber++;
    969 
    970   gBS->RestoreTPL (OldTpl);
    971 
    972   return EFI_SUCCESS;
    973 
    974 ON_ERROR:
    975 
    976   NetMapClean (&HttpInstance->TxTokens);
    977   NetMapClean (&HttpInstance->RxTokens);
    978   FreePool (HttpInstance);
    979 
    980   return Status;
    981 }
    982 
    983 /**
    984   Destroys a child handle with a protocol installed on it.
    985 
    986   The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
    987   that was installed by CreateChild() from ChildHandle. If the removed protocol is the
    988   last protocol on ChildHandle, then ChildHandle is destroyed.
    989 
    990   @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
    991   @param  ChildHandle Handle of the child to destroy
    992 
    993   @retval EFI_SUCCES            The protocol was removed from ChildHandle.
    994   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
    995   @retval EFI_INVALID_PARAMETER Child handle is NULL.
    996   @retval other                 The child handle was not destroyed
    997 
    998 **/
    999 EFI_STATUS
   1000 EFIAPI
   1001 HttpServiceBindingDestroyChild (
   1002   IN EFI_SERVICE_BINDING_PROTOCOL  *This,
   1003   IN EFI_HANDLE                    ChildHandle
   1004   )
   1005 {
   1006   HTTP_SERVICE             *HttpService;
   1007   HTTP_PROTOCOL            *HttpInstance;
   1008   EFI_HTTP_PROTOCOL        *Http;
   1009   EFI_STATUS                Status;
   1010   EFI_TPL                   OldTpl;
   1011 
   1012   if ((This == NULL) || (ChildHandle == NULL)) {
   1013     return EFI_INVALID_PARAMETER;
   1014   }
   1015 
   1016   HttpService = HTTP_SERVICE_FROM_PROTOCOL (This);
   1017   Status = gBS->OpenProtocol (
   1018                   ChildHandle,
   1019                   &gEfiHttpProtocolGuid,
   1020                   (VOID **) &Http,
   1021                   NULL,
   1022                   NULL,
   1023                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1024                   );
   1025   if (EFI_ERROR (Status)) {
   1026     return EFI_UNSUPPORTED;
   1027   }
   1028 
   1029   HttpInstance = HTTP_INSTANCE_FROM_PROTOCOL (Http);
   1030   if (HttpInstance->Service != HttpService) {
   1031     return EFI_INVALID_PARAMETER;
   1032   }
   1033 
   1034   if (HttpInstance->InDestroy) {
   1035     return EFI_SUCCESS;
   1036   }
   1037 
   1038   HttpInstance->InDestroy = TRUE;
   1039 
   1040   //
   1041   // Uninstall the HTTP protocol.
   1042   //
   1043   Status = gBS->UninstallProtocolInterface (
   1044                   ChildHandle,
   1045                   &gEfiHttpProtocolGuid,
   1046                   Http
   1047                   );
   1048 
   1049   if (EFI_ERROR (Status)) {
   1050     HttpInstance->InDestroy = FALSE;
   1051     return Status;
   1052   }
   1053 
   1054   HttpCleanProtocol (HttpInstance);
   1055 
   1056   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
   1057 
   1058   RemoveEntryList (&HttpInstance->Link);
   1059   HttpService->ChildrenNumber--;
   1060 
   1061   gBS->RestoreTPL (OldTpl);
   1062 
   1063   FreePool (HttpInstance);
   1064   return EFI_SUCCESS;
   1065 }
   1066