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
HttpCreateService(IN EFI_HANDLE Controller,IN EFI_HANDLE ImageHandle,OUT HTTP_SERVICE ** ServiceData)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
HttpCleanService(IN HTTP_SERVICE * HttpService,IN BOOLEAN UsingIpv6)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
HttpUtilitiesInstalledCallback(IN EFI_EVENT Event,IN VOID * Context)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
HttpDxeDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
HttpDestroyChildEntryInHandleBuffer(IN LIST_ENTRY * Entry,IN VOID * Context)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
HttpDxeSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN UINT8 IpVersion)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
HttpDxeStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL,IN UINT8 IpVersion)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
HttpDxeStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer,IN UINT8 IpVersion)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
HttpDxeIp4DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
HttpDxeIp4DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
HttpDxeIp4DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)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
HttpDxeIp6DriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
HttpDxeIp6DriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
HttpDxeIp6DriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer OPTIONAL)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
HttpServiceBindingCreateChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN OUT EFI_HANDLE * ChildHandle)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
HttpServiceBindingDestroyChild(IN EFI_SERVICE_BINDING_PROTOCOL * This,IN EFI_HANDLE ChildHandle)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