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