+/**\r
+ Test to see if this driver supports ControllerHandle. This is the worker function for\r
+ HttpDxeIp4(6)DriverBindingSupported.\r
+\r
+ @param[in] This The pointer to the driver binding protocol.\r
+ @param[in] ControllerHandle The handle of device to be tested.\r
+ @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
+ device to be started.\r
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
+ \r
+ @retval EFI_SUCCESS This driver supports this device.\r
+ @retval EFI_UNSUPPORTED This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeSupported (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,\r
+ IN UINT8 IpVersion\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_GUID *TcpServiceBindingProtocolGuid;\r
+\r
+ if (IpVersion == IP_VERSION_4) {\r
+ TcpServiceBindingProtocolGuid = &gEfiTcp4ServiceBindingProtocolGuid;\r
+ } else {\r
+ TcpServiceBindingProtocolGuid = &gEfiTcp6ServiceBindingProtocolGuid;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ TcpServiceBindingProtocolGuid,\r
+ NULL,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
+ );\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return EFI_UNSUPPORTED;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Start this driver on ControllerHandle. This is the worker function for\r
+ HttpDxeIp4(6)DriverBindingStart.\r
+\r
+ @param[in] This The pointer to the driver binding protocol.\r
+ @param[in] ControllerHandle The handle of device to be started.\r
+ @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
+ device to be started.\r
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
+\r
+\r
+ @retval EFI_SUCCESS This driver is installed to ControllerHandle.\r
+ @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
+ @retval other This driver does not support this device.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeStart (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL,\r
+ IN UINT8 IpVersion\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ HTTP_SERVICE *HttpService;\r
+ VOID *Interface;\r
+ BOOLEAN UsingIpv6;\r
+\r
+ UsingIpv6 = FALSE;\r
+\r
+ //\r
+ // Test for the Http service binding protocol\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ ControllerHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ (VOID **) &ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
+ } else {\r
+ Status = HttpCreateService (ControllerHandle, This->DriverBindingHandle, &HttpService);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ \r
+ ASSERT (HttpService != NULL);\r
+ \r
+ //\r
+ // Install the HttpServiceBinding Protocol onto Controller\r
+ //\r
+ Status = gBS->InstallMultipleProtocolInterfaces (\r
+ &ControllerHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ &HttpService->ServiceBinding,\r
+ NULL\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ }\r
+\r
+ if (IpVersion == IP_VERSION_4) {\r
+ \r
+ if (HttpService->Tcp4ChildHandle == NULL) {\r
+ //\r
+ // Create a TCP4 child instance, but do not configure it. This will establish the parent-child relationship.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ This->DriverBindingHandle,\r
+ &gEfiTcp4ServiceBindingProtocolGuid,\r
+ &HttpService->Tcp4ChildHandle\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ HttpService->Tcp4ChildHandle,\r
+ &gEfiTcp4ProtocolGuid,\r
+ &Interface,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ } else {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ } else {\r
+ UsingIpv6 = TRUE;\r
+ \r
+ if (HttpService->Tcp6ChildHandle == NULL) {\r
+ //\r
+ // Create a TCP6 child instance, but do not configure it. This will establish the parent-child relationship.\r
+ //\r
+ Status = NetLibCreateServiceChild (\r
+ ControllerHandle,\r
+ This->DriverBindingHandle,\r
+ &gEfiTcp6ServiceBindingProtocolGuid,\r
+ &HttpService->Tcp6ChildHandle\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ Status = gBS->OpenProtocol (\r
+ HttpService->Tcp6ChildHandle,\r
+ &gEfiTcp6ProtocolGuid,\r
+ &Interface,\r
+ This->DriverBindingHandle,\r
+ ControllerHandle,\r
+ EFI_OPEN_PROTOCOL_BY_DRIVER\r
+ );\r
+ \r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ \r
+ } else {\r
+ return EFI_ALREADY_STARTED;\r
+ }\r
+\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+ \r
+ON_ERROR:\r
+ \r
+ if (HttpService != NULL) {\r
+ HttpCleanService (HttpService, UsingIpv6);\r
+ if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {\r
+ FreePool (HttpService);\r
+ }\r
+ }\r
+ \r
+ return Status;\r
+\r
+\r
+}\r
+\r
+/**\r
+ Stop this driver on ControllerHandle. This is the worker function for\r
+ HttpDxeIp4(6)DriverBindingStop.\r
+\r
+ @param[in] This Protocol instance pointer.\r
+ @param[in] ControllerHandle Handle of device to stop driver on.\r
+ @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
+ children is zero stop the entire bus driver.\r
+ @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
+ @param[in] IpVersion IP_VERSION_4 or IP_VERSION_6.\r
+\r
+ @retval EFI_SUCCESS This driver was removed ControllerHandle.\r
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
+ @retval Others This driver was not removed from this device\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HttpDxeStop (\r
+ IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
+ IN EFI_HANDLE ControllerHandle,\r
+ IN UINTN NumberOfChildren,\r
+ IN EFI_HANDLE *ChildHandleBuffer,\r
+ IN UINT8 IpVersion\r
+ )\r
+{\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ HTTP_SERVICE *HttpService;\r
+ LIST_ENTRY *List;\r
+ HTTP_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
+ BOOLEAN UsingIpv6;\r
+\r
+ //\r
+ // HTTP driver opens TCP4(6) child, So, Controller is a TCP4(6)\r
+ // child handle. Locate the Nic handle first. Then get the\r
+ // HTTP private data back.\r
+ //\r
+ if (IpVersion == IP_VERSION_4) {\r
+ UsingIpv6 = FALSE;\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp4ProtocolGuid);\r
+ } else {\r
+ UsingIpv6 = TRUE;\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiTcp6ProtocolGuid);\r
+ }\r
+\r
+ if (NicHandle == NULL) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = gBS->OpenProtocol (\r
+ NicHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ (VOID **) &ServiceBinding,\r
+ This->DriverBindingHandle,\r
+ NicHandle,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ \r
+ HttpService = HTTP_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
+ \r
+ if (NumberOfChildren != 0) {\r
+ //\r
+ // Destroy the HTTP child instance in ChildHandleBuffer.\r
+ //\r
+ List = &HttpService->ChildrenList;\r
+ Context.ServiceBinding = ServiceBinding;\r
+ Context.NumberOfChildren = NumberOfChildren;\r
+ Context.ChildHandleBuffer = ChildHandleBuffer;\r
+ Status = NetDestroyLinkList (\r
+ List,\r
+ HttpDestroyChildEntryInHandleBuffer,\r
+ &Context,\r
+ NULL\r
+ );\r
+ } else {\r
+ \r
+ HttpCleanService (HttpService, UsingIpv6);\r
+ \r
+ if (HttpService->Tcp4ChildHandle == NULL && HttpService->Tcp6ChildHandle == NULL) {\r
+ gBS->UninstallProtocolInterface (\r
+ NicHandle,\r
+ &gEfiHttpServiceBindingProtocolGuid,\r
+ ServiceBinding\r
+ );\r
+ FreePool (HttpService);\r
+ }\r
+ Status = EFI_SUCCESS;\r
+ } \r
+ }\r
+ \r
+ return Status;\r
+\r
+}\r
+\r