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