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
18EFI_HTTP_UTILITIES_PROTOCOL *mHttpUtilities = NULL;
19
20///
21/// Driver Binding Protocol instance
22///
23EFI_DRIVER_BINDING_PROTOCOL gHttpDxeIp4DriverBinding = {
24  HttpDxeIp4DriverBindingSupported,
25  HttpDxeIp4DriverBindingStart,
26  HttpDxeIp4DriverBindingStop,
27  HTTP_DRIVER_VERSION,
28  NULL,
29  NULL
30};
31
32EFI_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**/
54EFI_STATUS
55HttpCreateService (
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**/
91VOID
92HttpCleanService (
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**/
149VOID
150EFIAPI
151HttpUtilitiesInstalledCallback (
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**/
182EFI_STATUS
183EFIAPI
184HttpDxeDriverEntryPoint (
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**/
260EFI_STATUS
261EFIAPI
262HttpDestroyChildEntryInHandleBuffer (
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**/
302EFI_STATUS
303EFIAPI
304HttpDxeSupported (
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**/
352EFI_STATUS
353EFIAPI
354HttpDxeStart (
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
479ON_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**/
509EFI_STATUS
510EFIAPI
511HttpDxeStop (
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**/
633EFI_STATUS
634EFIAPI
635HttpDxeIp4DriverBindingSupported (
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**/
685EFI_STATUS
686EFIAPI
687HttpDxeIp4DriverBindingStart (
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**/
727EFI_STATUS
728EFIAPI
729HttpDxeIp4DriverBindingStop (
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**/
787EFI_STATUS
788EFIAPI
789HttpDxeIp6DriverBindingSupported (
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**/
840EFI_STATUS
841EFIAPI
842HttpDxeIp6DriverBindingStart (
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**/
882EFI_STATUS
883EFIAPI
884HttpDxeIp6DriverBindingStop (
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**/
918EFI_STATUS
919EFIAPI
920HttpServiceBindingCreateChild (
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
974ON_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**/
999EFI_STATUS
1000EFIAPI
1001HttpServiceBindingDestroyChild (
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