2 Driver Binding functions implementation for UEFI HTTP boot.
4 Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials are licensed and made available under
6 the terms and conditions of the BSD License that accompanies this distribution.
7 The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php.
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "HttpBootDxe.h"
18 /// Driver Binding Protocol instance
20 EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp4DxeDriverBinding
= {
21 HttpBootIp4DxeDriverBindingSupported
,
22 HttpBootIp4DxeDriverBindingStart
,
23 HttpBootIp4DxeDriverBindingStop
,
24 HTTP_BOOT_DXE_VERSION
,
29 EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp6DxeDriverBinding
= {
30 HttpBootIp6DxeDriverBindingSupported
,
31 HttpBootIp6DxeDriverBindingStart
,
32 HttpBootIp6DxeDriverBindingStop
,
33 HTTP_BOOT_DXE_VERSION
,
41 Check whether UNDI protocol supports IPv6.
43 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
44 @param[out] Ipv6Support TRUE if UNDI supports IPv6.
46 @retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.
47 @retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available.
51 HttpBootCheckIpv6Support (
52 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
53 OUT BOOLEAN
*Ipv6Support
57 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
59 EFI_GUID
*InfoTypesBuffer
;
60 UINTN InfoTypeBufferCount
;
66 ASSERT (Private
!= NULL
&& Ipv6Support
!= NULL
);
69 // Check whether the UNDI supports IPv6 by NII protocol.
71 if (Private
->Nii
!= NULL
) {
72 *Ipv6Support
= Private
->Nii
->Ipv6Supported
;
77 // Get the NIC handle by SNP protocol.
79 Handle
= NetLibGetSnpHandle (Private
->Controller
, NULL
);
85 Status
= gBS
->HandleProtocol (
87 &gEfiAdapterInformationProtocolGuid
,
90 if (EFI_ERROR (Status
) || Aip
== NULL
) {
94 InfoTypesBuffer
= NULL
;
95 InfoTypeBufferCount
= 0;
96 Status
= Aip
->GetSupportedTypes (Aip
, &InfoTypesBuffer
, &InfoTypeBufferCount
);
97 if (EFI_ERROR (Status
) || InfoTypesBuffer
== NULL
) {
98 FreePool (InfoTypesBuffer
);
103 for (TypeIndex
= 0; TypeIndex
< InfoTypeBufferCount
; TypeIndex
++) {
104 if (CompareGuid (&InfoTypesBuffer
[TypeIndex
], &gEfiAdapterInfoUndiIpv6SupportGuid
)) {
110 FreePool (InfoTypesBuffer
);
112 return EFI_NOT_FOUND
;
116 // We now have adapter information block.
120 Status
= Aip
->GetInformation (Aip
, &gEfiAdapterInfoUndiIpv6SupportGuid
, &InfoBlock
, &InfoBlockSize
);
121 if (EFI_ERROR (Status
) || InfoBlock
== NULL
) {
122 FreePool (InfoBlock
);
123 return EFI_NOT_FOUND
;
126 *Ipv6Support
= ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT
*) InfoBlock
)->Ipv6Support
;
127 FreePool (InfoBlock
);
133 Destroy the HTTP child based on IPv4 stack.
135 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
136 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
140 HttpBootDestroyIp4Children (
141 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
142 IN HTTP_BOOT_PRIVATE_DATA
*Private
145 ASSERT (This
!= NULL
);
146 ASSERT (Private
!= NULL
);
148 if (Private
->Dhcp4Child
!= NULL
) {
151 &gEfiDhcp4ProtocolGuid
,
152 This
->DriverBindingHandle
,
156 NetLibDestroyServiceChild (
158 This
->DriverBindingHandle
,
159 &gEfiDhcp4ServiceBindingProtocolGuid
,
164 if (Private
->Ip6Nic
== NULL
&& Private
->HttpCreated
) {
165 HttpIoDestroyIo (&Private
->HttpIo
);
166 Private
->HttpCreated
= FALSE
;
169 if (Private
->Ip4Nic
!= NULL
) {
174 This
->DriverBindingHandle
,
175 Private
->Ip4Nic
->Controller
178 gBS
->UninstallMultipleProtocolInterfaces (
179 Private
->Ip4Nic
->Controller
,
180 &gEfiLoadFileProtocolGuid
,
181 &Private
->Ip4Nic
->LoadFile
,
182 &gEfiDevicePathProtocolGuid
,
183 Private
->Ip4Nic
->DevicePath
,
186 FreePool (Private
->Ip4Nic
);
187 Private
->Ip4Nic
= NULL
;
193 Destroy the HTTP child based on IPv6 stack.
195 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
196 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
200 HttpBootDestroyIp6Children (
201 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
202 IN HTTP_BOOT_PRIVATE_DATA
*Private
205 ASSERT (This
!= NULL
);
206 ASSERT (Private
!= NULL
);
208 if (Private
->Ip6Child
!= NULL
) {
211 &gEfiIp6ProtocolGuid
,
212 This
->DriverBindingHandle
,
216 NetLibDestroyServiceChild (
218 This
->DriverBindingHandle
,
219 &gEfiIp6ServiceBindingProtocolGuid
,
224 if (Private
->Dhcp6Child
!= NULL
) {
227 &gEfiDhcp6ProtocolGuid
,
228 This
->DriverBindingHandle
,
232 NetLibDestroyServiceChild (
234 This
->DriverBindingHandle
,
235 &gEfiDhcp6ServiceBindingProtocolGuid
,
240 if (Private
->Ip4Nic
== NULL
&& Private
->HttpCreated
) {
241 HttpIoDestroyIo(&Private
->HttpIo
);
242 Private
->HttpCreated
= FALSE
;
245 if (Private
->Ip6Nic
!= NULL
) {
250 This
->DriverBindingHandle
,
251 Private
->Ip6Nic
->Controller
254 gBS
->UninstallMultipleProtocolInterfaces (
255 Private
->Ip6Nic
->Controller
,
256 &gEfiLoadFileProtocolGuid
,
257 &Private
->Ip6Nic
->LoadFile
,
258 &gEfiDevicePathProtocolGuid
,
259 Private
->Ip6Nic
->DevicePath
,
262 FreePool (Private
->Ip6Nic
);
263 Private
->Ip6Nic
= NULL
;
268 Tests to see if this driver supports a given controller. If a child device is provided,
269 it further tests to see if this driver supports creating a handle for the specified child device.
271 This function checks to see if the driver specified by This supports the device specified by
272 ControllerHandle. Drivers will typically use the device path attached to
273 ControllerHandle and/or the services from the bus I/O abstraction attached to
274 ControllerHandle to determine if the driver supports ControllerHandle. This function
275 may be called many times during platform initialization. In order to reduce boot times, the tests
276 performed by this function must be very small, and take as little time as possible to execute. This
277 function must not change the state of any hardware devices, and this function must be aware that the
278 device specified by ControllerHandle may already be managed by the same driver or a
279 different driver. This function must match its calls to AllocatePages() with FreePages(),
280 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
281 Because ControllerHandle may have been previously started by the same driver, if a protocol is
282 already in the opened state, then it must not be closed with CloseProtocol(). This is required
283 to guarantee the state of ControllerHandle is not modified by this function.
285 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
286 @param[in] ControllerHandle The handle of the controller to test. This handle
287 must support a protocol interface that supplies
288 an I/O abstraction to the driver.
289 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
290 parameter is ignored by device drivers, and is optional for bus
291 drivers. For bus drivers, if this parameter is not NULL, then
292 the bus driver must determine if the bus controller specified
293 by ControllerHandle and the child controller specified
294 by RemainingDevicePath are both supported by this
297 @retval EFI_SUCCESS The device specified by ControllerHandle and
298 RemainingDevicePath is supported by the driver specified by This.
299 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
300 RemainingDevicePath is already being managed by the driver
302 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
303 RemainingDevicePath is already being managed by a different
304 driver or an application that requires exclusive access.
305 Currently not implemented.
306 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
307 RemainingDevicePath is not supported by the driver specified by This.
311 HttpBootIp4DxeDriverBindingSupported (
312 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
313 IN EFI_HANDLE ControllerHandle
,
314 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
320 // Try to open the DHCP4, HTTP4 and Device Path protocol.
322 Status
= gBS
->OpenProtocol (
324 &gEfiDhcp4ServiceBindingProtocolGuid
,
326 This
->DriverBindingHandle
,
328 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
330 if (EFI_ERROR (Status
)) {
334 Status
= gBS
->OpenProtocol (
336 &gEfiHttpServiceBindingProtocolGuid
,
338 This
->DriverBindingHandle
,
340 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
342 if (EFI_ERROR (Status
)) {
346 Status
= gBS
->OpenProtocol (
348 &gEfiDevicePathProtocolGuid
,
350 This
->DriverBindingHandle
,
352 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
360 Starts a device controller or a bus controller.
362 The Start() function is designed to be invoked from the EFI boot service ConnectController().
363 As a result, much of the error checking on the parameters to Start() has been moved into this
364 common boot service. It is legal to call Start() from other locations,
365 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
366 1. ControllerHandle must be a valid EFI_HANDLE.
367 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
368 EFI_DEVICE_PATH_PROTOCOL.
369 3. Prior to calling Start(), the Supported() function for the driver specified by This must
370 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
372 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
373 @param[in] ControllerHandle The handle of the controller to start. This handle
374 must support a protocol interface that supplies
375 an I/O abstraction to the driver.
376 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
377 parameter is ignored by device drivers, and is optional for bus
378 drivers. For a bus driver, if this parameter is NULL, then handles
379 for all the children of Controller are created by this driver.
380 If this parameter is not NULL and the first Device Path Node is
381 not the End of Device Path Node, then only the handle for the
382 child device specified by the first Device Path Node of
383 RemainingDevicePath is created by this driver.
384 If the first Device Path Node of RemainingDevicePath is
385 the End of Device Path Node, no child handle is created by this
388 @retval EFI_SUCCESS The device was started.
389 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
390 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
391 @retval Others The driver failded to start the device.
396 HttpBootIp4DxeDriverBindingStart (
397 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
398 IN EFI_HANDLE ControllerHandle
,
399 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
403 HTTP_BOOT_PRIVATE_DATA
*Private
;
405 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
411 Status
= gBS
->OpenProtocol (
415 This
->DriverBindingHandle
,
417 EFI_OPEN_PROTOCOL_GET_PROTOCOL
420 if (!EFI_ERROR (Status
)) {
421 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id
);
426 // Initialize the private data structure.
428 Private
= AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA
));
429 if (Private
== NULL
) {
430 return EFI_OUT_OF_RESOURCES
;
432 Private
->Signature
= HTTP_BOOT_PRIVATE_DATA_SIGNATURE
;
433 Private
->Controller
= ControllerHandle
;
434 InitializeListHead (&Private
->CacheList
);
436 // Get the NII interface if it exists, it's not required.
438 Status
= gBS
->OpenProtocol (
440 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
441 (VOID
**) &Private
->Nii
,
442 This
->DriverBindingHandle
,
444 EFI_OPEN_PROTOCOL_GET_PROTOCOL
446 if (EFI_ERROR (Status
)) {
451 // Open Device Path Protocol to prepare for appending IP and URI node.
453 Status
= gBS
->OpenProtocol (
455 &gEfiDevicePathProtocolGuid
,
456 (VOID
**) &Private
->ParentDevicePath
,
457 This
->DriverBindingHandle
,
459 EFI_OPEN_PROTOCOL_GET_PROTOCOL
461 if (EFI_ERROR (Status
)) {
466 // Initialize the HII configuration form.
468 Status
= HttpBootConfigFormInit (Private
);
469 if (EFI_ERROR (Status
)) {
474 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
475 // NIC handle and the private data.
477 Status
= gBS
->InstallProtocolInterface (
480 EFI_NATIVE_INTERFACE
,
483 if (EFI_ERROR (Status
)) {
489 if (Private
->Ip4Nic
!= NULL
) {
491 // Already created before
496 Private
->Ip4Nic
= AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC
));
497 if (Private
->Ip4Nic
== NULL
) {
498 Status
= EFI_OUT_OF_RESOURCES
;
501 Private
->Ip4Nic
->Private
= Private
;
502 Private
->Ip4Nic
->ImageHandle
= This
->DriverBindingHandle
;
503 Private
->Ip4Nic
->Signature
= HTTP_BOOT_VIRTUAL_NIC_SIGNATURE
;
506 // Create DHCP4 child instance.
508 Status
= NetLibCreateServiceChild (
510 This
->DriverBindingHandle
,
511 &gEfiDhcp4ServiceBindingProtocolGuid
,
514 if (EFI_ERROR (Status
)) {
518 Status
= gBS
->OpenProtocol (
520 &gEfiDhcp4ProtocolGuid
,
521 (VOID
**) &Private
->Dhcp4
,
522 This
->DriverBindingHandle
,
524 EFI_OPEN_PROTOCOL_BY_DRIVER
526 if (EFI_ERROR (Status
)) {
531 // Get the Ip4Config2 protocol, it's required to configure the default gateway address.
533 Status
= gBS
->OpenProtocol (
535 &gEfiIp4Config2ProtocolGuid
,
536 (VOID
**) &Private
->Ip4Config2
,
537 This
->DriverBindingHandle
,
539 EFI_OPEN_PROTOCOL_GET_PROTOCOL
541 if (EFI_ERROR (Status
)) {
546 // Append IPv4 device path node.
548 Node
= AllocateZeroPool (sizeof (IPv4_DEVICE_PATH
));
550 Status
= EFI_OUT_OF_RESOURCES
;
553 Node
->Ipv4
.Header
.Type
= MESSAGING_DEVICE_PATH
;
554 Node
->Ipv4
.Header
.SubType
= MSG_IPv4_DP
;
555 SetDevicePathNodeLength (Node
, sizeof (IPv4_DEVICE_PATH
));
556 Node
->Ipv4
.StaticIpAddress
= FALSE
;
557 DevicePath
= AppendDevicePathNode (Private
->ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
559 if (DevicePath
== NULL
) {
560 Status
= EFI_OUT_OF_RESOURCES
;
565 // Append URI device path node.
567 Node
= AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL
));
569 Status
= EFI_OUT_OF_RESOURCES
;
572 Node
->DevPath
.Type
= MESSAGING_DEVICE_PATH
;
573 Node
->DevPath
.SubType
= MSG_URI_DP
;
574 SetDevicePathNodeLength (Node
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
575 Private
->Ip4Nic
->DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
577 FreePool (DevicePath
);
578 if (Private
->Ip4Nic
->DevicePath
== NULL
) {
579 Status
= EFI_OUT_OF_RESOURCES
;
584 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
586 CopyMem (&Private
->Ip4Nic
->LoadFile
, &gHttpBootDxeLoadFile
, sizeof (EFI_LOAD_FILE_PROTOCOL
));
587 Status
= gBS
->InstallMultipleProtocolInterfaces (
588 &Private
->Ip4Nic
->Controller
,
589 &gEfiLoadFileProtocolGuid
,
590 &Private
->Ip4Nic
->LoadFile
,
591 &gEfiDevicePathProtocolGuid
,
592 Private
->Ip4Nic
->DevicePath
,
595 if (EFI_ERROR (Status
)) {
600 // Open the Caller Id child to setup a parent-child relationship between
601 // real NIC handle and the HTTP boot Ipv4 NIC handle.
603 Status
= gBS
->OpenProtocol (
607 This
->DriverBindingHandle
,
608 Private
->Ip4Nic
->Controller
,
609 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
611 if (EFI_ERROR (Status
)) {
619 gBS
->UninstallProtocolInterface (
626 HttpBootDestroyIp4Children (This
, Private
);
627 HttpBootConfigFormUnload (Private
);
629 if (FirstStart
&& Private
!= NULL
) {
638 Stops a device controller or a bus controller.
640 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
641 As a result, much of the error checking on the parameters to Stop() has been moved
642 into this common boot service. It is legal to call Stop() from other locations,
643 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
644 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
645 same driver's Start() function.
646 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
647 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
648 Start() function, and the Start() function must have called OpenProtocol() on
649 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
651 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
652 @param[in] ControllerHandle A handle to the device being stopped. The handle must
653 support a bus specific I/O protocol for the driver
654 to use to stop the device.
655 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
656 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
657 if NumberOfChildren is 0.
659 @retval EFI_SUCCESS The device was stopped.
660 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
665 HttpBootIp4DxeDriverBindingStop (
666 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
667 IN EFI_HANDLE ControllerHandle
,
668 IN UINTN NumberOfChildren
,
669 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
673 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
674 HTTP_BOOT_PRIVATE_DATA
*Private
;
675 EFI_HANDLE NicHandle
;
679 // Try to get the Load File Protocol from the controller handle.
681 Status
= gBS
->OpenProtocol (
683 &gEfiLoadFileProtocolGuid
,
685 This
->DriverBindingHandle
,
687 EFI_OPEN_PROTOCOL_GET_PROTOCOL
689 if (EFI_ERROR (Status
)) {
691 // If failed, try to find the NIC handle for this controller.
693 NicHandle
= HttpBootGetNicByIp4Children (ControllerHandle
);
694 if (NicHandle
== NULL
) {
699 // Try to retrieve the private data by the Caller Id Guid.
701 Status
= gBS
->OpenProtocol (
705 This
->DriverBindingHandle
,
707 EFI_OPEN_PROTOCOL_GET_PROTOCOL
709 if (EFI_ERROR (Status
)) {
712 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id
);
714 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile
);
715 NicHandle
= Private
->Controller
;
719 // Disable the HTTP boot function.
721 Status
= HttpBootStop (Private
);
722 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
727 // Destory all child instance and uninstall protocol interface.
729 HttpBootDestroyIp4Children (This
, Private
);
731 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
733 // Release the cached data.
735 HttpBootFreeCacheList (Private
);
738 // Unload the config form.
740 HttpBootConfigFormUnload (Private
);
742 gBS
->UninstallProtocolInterface (
755 Tests to see if this driver supports a given controller. If a child device is provided,
756 it further tests to see if this driver supports creating a handle for the specified child device.
758 This function checks to see if the driver specified by This supports the device specified by
759 ControllerHandle. Drivers will typically use the device path attached to
760 ControllerHandle and/or the services from the bus I/O abstraction attached to
761 ControllerHandle to determine if the driver supports ControllerHandle. This function
762 may be called many times during platform initialization. In order to reduce boot times, the tests
763 performed by this function must be very small, and take as little time as possible to execute. This
764 function must not change the state of any hardware devices, and this function must be aware that the
765 device specified by ControllerHandle may already be managed by the same driver or a
766 different driver. This function must match its calls to AllocatePages() with FreePages(),
767 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
768 Because ControllerHandle may have been previously started by the same driver, if a protocol is
769 already in the opened state, then it must not be closed with CloseProtocol(). This is required
770 to guarantee the state of ControllerHandle is not modified by this function.
772 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
773 @param[in] ControllerHandle The handle of the controller to test. This handle
774 must support a protocol interface that supplies
775 an I/O abstraction to the driver.
776 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
777 parameter is ignored by device drivers, and is optional for bus
778 drivers. For bus drivers, if this parameter is not NULL, then
779 the bus driver must determine if the bus controller specified
780 by ControllerHandle and the child controller specified
781 by RemainingDevicePath are both supported by this
784 @retval EFI_SUCCESS The device specified by ControllerHandle and
785 RemainingDevicePath is supported by the driver specified by This.
786 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
787 RemainingDevicePath is already being managed by the driver
789 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
790 RemainingDevicePath is already being managed by a different
791 driver or an application that requires exclusive access.
792 Currently not implemented.
793 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
794 RemainingDevicePath is not supported by the driver specified by This.
798 HttpBootIp6DxeDriverBindingSupported (
799 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
800 IN EFI_HANDLE ControllerHandle
,
801 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
807 // Try to open the DHCP6, HTTP and Device Path protocol.
809 Status
= gBS
->OpenProtocol (
811 &gEfiDhcp6ServiceBindingProtocolGuid
,
813 This
->DriverBindingHandle
,
815 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
817 if (EFI_ERROR (Status
)) {
821 Status
= gBS
->OpenProtocol (
823 &gEfiHttpServiceBindingProtocolGuid
,
825 This
->DriverBindingHandle
,
827 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
829 if (EFI_ERROR (Status
)) {
833 Status
= gBS
->OpenProtocol (
835 &gEfiDevicePathProtocolGuid
,
837 This
->DriverBindingHandle
,
839 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
847 Starts a device controller or a bus controller.
849 The Start() function is designed to be invoked from the EFI boot service ConnectController().
850 As a result, much of the error checking on the parameters to Start() has been moved into this
851 common boot service. It is legal to call Start() from other locations,
852 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
853 1. ControllerHandle must be a valid EFI_HANDLE.
854 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
855 EFI_DEVICE_PATH_PROTOCOL.
856 3. Prior to calling Start(), the Supported() function for the driver specified by This must
857 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
859 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
860 @param[in] ControllerHandle The handle of the controller to start. This handle
861 must support a protocol interface that supplies
862 an I/O abstraction to the driver.
863 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
864 parameter is ignored by device drivers, and is optional for bus
865 drivers. For a bus driver, if this parameter is NULL, then handles
866 for all the children of Controller are created by this driver.
867 If this parameter is not NULL and the first Device Path Node is
868 not the End of Device Path Node, then only the handle for the
869 child device specified by the first Device Path Node of
870 RemainingDevicePath is created by this driver.
871 If the first Device Path Node of RemainingDevicePath is
872 the End of Device Path Node, no child handle is created by this
875 @retval EFI_SUCCESS The device was started.
876 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
877 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
878 @retval Others The driver failded to start the device.
883 HttpBootIp6DxeDriverBindingStart (
884 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
885 IN EFI_HANDLE ControllerHandle
,
886 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
890 HTTP_BOOT_PRIVATE_DATA
*Private
;
892 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
894 BOOLEAN Ipv6Available
;
899 Status
= gBS
->OpenProtocol (
903 This
->DriverBindingHandle
,
905 EFI_OPEN_PROTOCOL_GET_PROTOCOL
908 if (!EFI_ERROR (Status
)) {
909 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id
);
914 // Initialize the private data structure.
916 Private
= AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA
));
917 if (Private
== NULL
) {
918 return EFI_OUT_OF_RESOURCES
;
920 Private
->Signature
= HTTP_BOOT_PRIVATE_DATA_SIGNATURE
;
921 Private
->Controller
= ControllerHandle
;
922 InitializeListHead (&Private
->CacheList
);
924 // Get the NII interface if it exists, it's not required.
926 Status
= gBS
->OpenProtocol (
928 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
929 (VOID
**) &Private
->Nii
,
930 This
->DriverBindingHandle
,
932 EFI_OPEN_PROTOCOL_GET_PROTOCOL
934 if (EFI_ERROR (Status
)) {
939 // Open Device Path Protocol to prepare for appending IP and URI node.
941 Status
= gBS
->OpenProtocol (
943 &gEfiDevicePathProtocolGuid
,
944 (VOID
**) &Private
->ParentDevicePath
,
945 This
->DriverBindingHandle
,
947 EFI_OPEN_PROTOCOL_GET_PROTOCOL
949 if (EFI_ERROR (Status
)) {
954 // Initialize the HII configuration form.
956 Status
= HttpBootConfigFormInit (Private
);
957 if (EFI_ERROR (Status
)) {
962 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
963 // NIC handle and the private data.
965 Status
= gBS
->InstallProtocolInterface (
968 EFI_NATIVE_INTERFACE
,
971 if (EFI_ERROR (Status
)) {
978 // Set IPv6 available flag.
980 Status
= HttpBootCheckIpv6Support (Private
, &Ipv6Available
);
981 if (EFI_ERROR (Status
)) {
983 // Fail to get the data whether UNDI supports IPv6.
984 // Set default value to TRUE.
986 Ipv6Available
= TRUE
;
989 if (!Ipv6Available
) {
990 Status
= EFI_UNSUPPORTED
;
994 if (Private
->Ip6Nic
!= NULL
) {
996 // Already created before
1001 Private
->Ip6Nic
= AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC
));
1002 if (Private
->Ip6Nic
== NULL
) {
1003 Status
= EFI_OUT_OF_RESOURCES
;
1006 Private
->Ip6Nic
->Private
= Private
;
1007 Private
->Ip6Nic
->ImageHandle
= This
->DriverBindingHandle
;
1008 Private
->Ip6Nic
->Signature
= HTTP_BOOT_VIRTUAL_NIC_SIGNATURE
;
1011 // Create Dhcp6 child and open Dhcp6 protocol
1012 Status
= NetLibCreateServiceChild (
1014 This
->DriverBindingHandle
,
1015 &gEfiDhcp6ServiceBindingProtocolGuid
,
1016 &Private
->Dhcp6Child
1018 if (EFI_ERROR (Status
)) {
1022 Status
= gBS
->OpenProtocol (
1023 Private
->Dhcp6Child
,
1024 &gEfiDhcp6ProtocolGuid
,
1025 (VOID
**) &Private
->Dhcp6
,
1026 This
->DriverBindingHandle
,
1028 EFI_OPEN_PROTOCOL_BY_DRIVER
1030 if (EFI_ERROR (Status
)) {
1035 // Create Ip6 child and open Ip6 protocol for background ICMP packets.
1037 Status
= NetLibCreateServiceChild (
1039 This
->DriverBindingHandle
,
1040 &gEfiIp6ServiceBindingProtocolGuid
,
1043 if (EFI_ERROR (Status
)) {
1047 Status
= gBS
->OpenProtocol (
1049 &gEfiIp6ProtocolGuid
,
1050 (VOID
**) &Private
->Ip6
,
1051 This
->DriverBindingHandle
,
1053 EFI_OPEN_PROTOCOL_BY_DRIVER
1055 if (EFI_ERROR (Status
)) {
1060 // Locate Ip6Config protocol, it's required to configure the default gateway address.
1062 Status
= gBS
->OpenProtocol (
1064 &gEfiIp6ConfigProtocolGuid
,
1065 (VOID
**) &Private
->Ip6Config
,
1066 This
->DriverBindingHandle
,
1068 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1070 if (EFI_ERROR (Status
)) {
1075 // Append IPv6 device path node.
1077 Node
= AllocateZeroPool (sizeof (IPv6_DEVICE_PATH
));
1079 Status
= EFI_OUT_OF_RESOURCES
;
1082 Node
->Ipv6
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1083 Node
->Ipv6
.Header
.SubType
= MSG_IPv6_DP
;
1084 Node
->Ipv6
.PrefixLength
= IP6_PREFIX_LENGTH
;
1085 SetDevicePathNodeLength (Node
, sizeof (IPv6_DEVICE_PATH
));
1086 DevicePath
= AppendDevicePathNode(Private
->ParentDevicePath
, (EFI_DEVICE_PATH
*) Node
);
1088 if (DevicePath
== NULL
) {
1089 Status
= EFI_OUT_OF_RESOURCES
;
1094 // Append URI device path node.
1096 Node
= AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL
));
1098 Status
= EFI_OUT_OF_RESOURCES
;
1101 Node
->DevPath
.Type
= MESSAGING_DEVICE_PATH
;
1102 Node
->DevPath
.SubType
= MSG_URI_DP
;
1103 SetDevicePathNodeLength (Node
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
1104 Private
->Ip6Nic
->DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
1106 FreePool (DevicePath
);
1107 if (Private
->Ip6Nic
->DevicePath
== NULL
) {
1108 Status
= EFI_OUT_OF_RESOURCES
;
1113 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
1115 CopyMem (&Private
->Ip6Nic
->LoadFile
, &gHttpBootDxeLoadFile
, sizeof (Private
->LoadFile
));
1116 Status
= gBS
->InstallMultipleProtocolInterfaces (
1117 &Private
->Ip6Nic
->Controller
,
1118 &gEfiLoadFileProtocolGuid
,
1119 &Private
->Ip6Nic
->LoadFile
,
1120 &gEfiDevicePathProtocolGuid
,
1121 Private
->Ip6Nic
->DevicePath
,
1124 if (EFI_ERROR (Status
)) {
1129 // Open the Caller Id child to setup a parent-child relationship between
1130 // real NIC handle and the HTTP boot child handle.
1132 Status
= gBS
->OpenProtocol (
1136 This
->DriverBindingHandle
,
1137 Private
->Ip6Nic
->Controller
,
1138 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1140 if (EFI_ERROR (Status
)) {
1148 gBS
->UninstallProtocolInterface (
1155 HttpBootDestroyIp6Children(This
, Private
);
1156 HttpBootConfigFormUnload (Private
);
1158 if (FirstStart
&& Private
!= NULL
) {
1166 Stops a device controller or a bus controller.
1168 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1169 As a result, much of the error checking on the parameters to Stop() has been moved
1170 into this common boot service. It is legal to call Stop() from other locations,
1171 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1172 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1173 same driver's Start() function.
1174 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1175 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1176 Start() function, and the Start() function must have called OpenProtocol() on
1177 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1179 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1180 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1181 support a bus specific I/O protocol for the driver
1182 to use to stop the device.
1183 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1184 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1185 if NumberOfChildren is 0.
1187 @retval EFI_SUCCESS The device was stopped.
1188 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1193 HttpBootIp6DxeDriverBindingStop (
1194 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1195 IN EFI_HANDLE ControllerHandle
,
1196 IN UINTN NumberOfChildren
,
1197 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1201 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1202 HTTP_BOOT_PRIVATE_DATA
*Private
;
1203 EFI_HANDLE NicHandle
;
1207 // Try to get the Load File Protocol from the controller handle.
1209 Status
= gBS
->OpenProtocol (
1211 &gEfiLoadFileProtocolGuid
,
1212 (VOID
**) &LoadFile
,
1213 This
->DriverBindingHandle
,
1215 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1217 if (EFI_ERROR (Status
)) {
1219 // If failed, try to find the NIC handle for this controller.
1221 NicHandle
= HttpBootGetNicByIp6Children (ControllerHandle
);
1222 if (NicHandle
== NULL
) {
1227 // Try to retrieve the private data by the Caller Id Guid.
1229 Status
= gBS
->OpenProtocol (
1233 This
->DriverBindingHandle
,
1235 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1237 if (EFI_ERROR (Status
)) {
1240 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id
);
1242 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile
);
1243 NicHandle
= Private
->Controller
;
1247 // Disable the HTTP boot function.
1249 Status
= HttpBootStop (Private
);
1250 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
1255 // Destory all child instance and uninstall protocol interface.
1257 HttpBootDestroyIp6Children (This
, Private
);
1259 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
1261 // Release the cached data.
1263 HttpBootFreeCacheList (Private
);
1266 // Unload the config form.
1268 HttpBootConfigFormUnload (Private
);
1270 gBS
->UninstallProtocolInterface (
1282 This is the declaration of an EFI image entry point. This entry point is
1283 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1284 both device drivers and bus drivers.
1286 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1287 @param[in] SystemTable A pointer to the EFI System Table.
1289 @retval EFI_SUCCESS The operation completed successfully.
1290 @retval Others An unexpected error occurred.
1295 HttpBootDxeDriverEntryPoint (
1296 IN EFI_HANDLE ImageHandle
,
1297 IN EFI_SYSTEM_TABLE
*SystemTable
1303 // Install UEFI Driver Model protocol(s).
1305 Status
= EfiLibInstallDriverBindingComponentName2 (
1308 &gHttpBootIp4DxeDriverBinding
,
1310 &gHttpBootDxeComponentName
,
1311 &gHttpBootDxeComponentName2
1313 if (EFI_ERROR (Status
)) {
1317 Status
= EfiLibInstallDriverBindingComponentName2 (
1320 &gHttpBootIp6DxeDriverBinding
,
1322 &gHttpBootDxeComponentName
,
1323 &gHttpBootDxeComponentName2
1325 if (EFI_ERROR (Status
)) {
1326 gBS
->UninstallMultipleProtocolInterfaces(
1328 &gEfiDriverBindingProtocolGuid
,
1329 &gHttpBootIp4DxeDriverBinding
,
1330 &gEfiComponentName2ProtocolGuid
,
1331 &gHttpBootDxeComponentName2
,
1332 &gEfiComponentNameProtocolGuid
,
1333 &gHttpBootDxeComponentName
,