2 Driver Binding functions implementation for UEFI HTTP boot.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "HttpBootDxe.h"
12 /// Driver Binding Protocol instance
14 EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp4DxeDriverBinding
= {
15 HttpBootIp4DxeDriverBindingSupported
,
16 HttpBootIp4DxeDriverBindingStart
,
17 HttpBootIp4DxeDriverBindingStop
,
18 HTTP_BOOT_DXE_VERSION
,
23 EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp6DxeDriverBinding
= {
24 HttpBootIp6DxeDriverBindingSupported
,
25 HttpBootIp6DxeDriverBindingStart
,
26 HttpBootIp6DxeDriverBindingStop
,
27 HTTP_BOOT_DXE_VERSION
,
35 Check whether UNDI protocol supports IPv6.
37 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
38 @param[out] Ipv6Support TRUE if UNDI supports IPv6.
40 @retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.
41 @retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available.
45 HttpBootCheckIpv6Support (
46 IN HTTP_BOOT_PRIVATE_DATA
*Private
,
47 OUT BOOLEAN
*Ipv6Support
51 EFI_ADAPTER_INFORMATION_PROTOCOL
*Aip
;
53 EFI_GUID
*InfoTypesBuffer
;
54 UINTN InfoTypeBufferCount
;
60 ASSERT (Private
!= NULL
&& Ipv6Support
!= NULL
);
63 // Check whether the UNDI supports IPv6 by NII protocol.
65 if (Private
->Nii
!= NULL
) {
66 *Ipv6Support
= Private
->Nii
->Ipv6Supported
;
71 // Get the NIC handle by SNP protocol.
73 Handle
= NetLibGetSnpHandle (Private
->Controller
, NULL
);
79 Status
= gBS
->HandleProtocol (
81 &gEfiAdapterInformationProtocolGuid
,
84 if (EFI_ERROR (Status
) || Aip
== NULL
) {
88 InfoTypesBuffer
= NULL
;
89 InfoTypeBufferCount
= 0;
90 Status
= Aip
->GetSupportedTypes (Aip
, &InfoTypesBuffer
, &InfoTypeBufferCount
);
91 if (EFI_ERROR (Status
) || InfoTypesBuffer
== NULL
) {
92 FreePool (InfoTypesBuffer
);
97 for (TypeIndex
= 0; TypeIndex
< InfoTypeBufferCount
; TypeIndex
++) {
98 if (CompareGuid (&InfoTypesBuffer
[TypeIndex
], &gEfiAdapterInfoUndiIpv6SupportGuid
)) {
104 FreePool (InfoTypesBuffer
);
106 return EFI_NOT_FOUND
;
110 // We now have adapter information block.
114 Status
= Aip
->GetInformation (Aip
, &gEfiAdapterInfoUndiIpv6SupportGuid
, &InfoBlock
, &InfoBlockSize
);
115 if (EFI_ERROR (Status
) || InfoBlock
== NULL
) {
116 FreePool (InfoBlock
);
117 return EFI_NOT_FOUND
;
120 *Ipv6Support
= ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT
*) InfoBlock
)->Ipv6Support
;
121 FreePool (InfoBlock
);
127 Destroy the HTTP child based on IPv4 stack.
129 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
130 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
134 HttpBootDestroyIp4Children (
135 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
136 IN HTTP_BOOT_PRIVATE_DATA
*Private
139 ASSERT (This
!= NULL
);
140 ASSERT (Private
!= NULL
);
142 if (Private
->Dhcp4Child
!= NULL
) {
145 &gEfiDhcp4ProtocolGuid
,
146 This
->DriverBindingHandle
,
150 NetLibDestroyServiceChild (
152 This
->DriverBindingHandle
,
153 &gEfiDhcp4ServiceBindingProtocolGuid
,
158 if (Private
->Ip6Nic
== NULL
&& Private
->HttpCreated
) {
159 HttpIoDestroyIo (&Private
->HttpIo
);
160 Private
->HttpCreated
= FALSE
;
163 if (Private
->Ip4Nic
!= NULL
) {
168 This
->DriverBindingHandle
,
169 Private
->Ip4Nic
->Controller
172 gBS
->UninstallMultipleProtocolInterfaces (
173 Private
->Ip4Nic
->Controller
,
174 &gEfiLoadFileProtocolGuid
,
175 &Private
->Ip4Nic
->LoadFile
,
176 &gEfiDevicePathProtocolGuid
,
177 Private
->Ip4Nic
->DevicePath
,
180 FreePool (Private
->Ip4Nic
);
181 Private
->Ip4Nic
= NULL
;
187 Destroy the HTTP child based on IPv6 stack.
189 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
190 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
194 HttpBootDestroyIp6Children (
195 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
196 IN HTTP_BOOT_PRIVATE_DATA
*Private
199 ASSERT (This
!= NULL
);
200 ASSERT (Private
!= NULL
);
202 if (Private
->Ip6Child
!= NULL
) {
205 &gEfiIp6ProtocolGuid
,
206 This
->DriverBindingHandle
,
210 NetLibDestroyServiceChild (
212 This
->DriverBindingHandle
,
213 &gEfiIp6ServiceBindingProtocolGuid
,
218 if (Private
->Dhcp6Child
!= NULL
) {
221 &gEfiDhcp6ProtocolGuid
,
222 This
->DriverBindingHandle
,
226 NetLibDestroyServiceChild (
228 This
->DriverBindingHandle
,
229 &gEfiDhcp6ServiceBindingProtocolGuid
,
234 if (Private
->Ip4Nic
== NULL
&& Private
->HttpCreated
) {
235 HttpIoDestroyIo(&Private
->HttpIo
);
236 Private
->HttpCreated
= FALSE
;
239 if (Private
->Ip6Nic
!= NULL
) {
244 This
->DriverBindingHandle
,
245 Private
->Ip6Nic
->Controller
248 gBS
->UninstallMultipleProtocolInterfaces (
249 Private
->Ip6Nic
->Controller
,
250 &gEfiLoadFileProtocolGuid
,
251 &Private
->Ip6Nic
->LoadFile
,
252 &gEfiDevicePathProtocolGuid
,
253 Private
->Ip6Nic
->DevicePath
,
256 FreePool (Private
->Ip6Nic
);
257 Private
->Ip6Nic
= NULL
;
262 Tests to see if this driver supports a given controller. If a child device is provided,
263 it further tests to see if this driver supports creating a handle for the specified child device.
265 This function checks to see if the driver specified by This supports the device specified by
266 ControllerHandle. Drivers will typically use the device path attached to
267 ControllerHandle and/or the services from the bus I/O abstraction attached to
268 ControllerHandle to determine if the driver supports ControllerHandle. This function
269 may be called many times during platform initialization. In order to reduce boot times, the tests
270 performed by this function must be very small, and take as little time as possible to execute. This
271 function must not change the state of any hardware devices, and this function must be aware that the
272 device specified by ControllerHandle may already be managed by the same driver or a
273 different driver. This function must match its calls to AllocatePages() with FreePages(),
274 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
275 Because ControllerHandle may have been previously started by the same driver, if a protocol is
276 already in the opened state, then it must not be closed with CloseProtocol(). This is required
277 to guarantee the state of ControllerHandle is not modified by this function.
279 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
280 @param[in] ControllerHandle The handle of the controller to test. This handle
281 must support a protocol interface that supplies
282 an I/O abstraction to the driver.
283 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
284 parameter is ignored by device drivers, and is optional for bus
285 drivers. For bus drivers, if this parameter is not NULL, then
286 the bus driver must determine if the bus controller specified
287 by ControllerHandle and the child controller specified
288 by RemainingDevicePath are both supported by this
291 @retval EFI_SUCCESS The device specified by ControllerHandle and
292 RemainingDevicePath is supported by the driver specified by This.
293 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
294 RemainingDevicePath is already being managed by the driver
296 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
297 RemainingDevicePath is already being managed by a different
298 driver or an application that requires exclusive access.
299 Currently not implemented.
300 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
301 RemainingDevicePath is not supported by the driver specified by This.
305 HttpBootIp4DxeDriverBindingSupported (
306 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
307 IN EFI_HANDLE ControllerHandle
,
308 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
314 // Try to open the DHCP4, HTTP4 and Device Path protocol.
316 Status
= gBS
->OpenProtocol (
318 &gEfiDhcp4ServiceBindingProtocolGuid
,
320 This
->DriverBindingHandle
,
322 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
324 if (EFI_ERROR (Status
)) {
328 Status
= gBS
->OpenProtocol (
330 &gEfiHttpServiceBindingProtocolGuid
,
332 This
->DriverBindingHandle
,
334 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
336 if (EFI_ERROR (Status
)) {
340 Status
= gBS
->OpenProtocol (
342 &gEfiDevicePathProtocolGuid
,
344 This
->DriverBindingHandle
,
346 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
354 Starts a device controller or a bus controller.
356 The Start() function is designed to be invoked from the EFI boot service ConnectController().
357 As a result, much of the error checking on the parameters to Start() has been moved into this
358 common boot service. It is legal to call Start() from other locations,
359 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
360 1. ControllerHandle must be a valid EFI_HANDLE.
361 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
362 EFI_DEVICE_PATH_PROTOCOL.
363 3. Prior to calling Start(), the Supported() function for the driver specified by This must
364 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
366 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
367 @param[in] ControllerHandle The handle of the controller to start. This handle
368 must support a protocol interface that supplies
369 an I/O abstraction to the driver.
370 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
371 parameter is ignored by device drivers, and is optional for bus
372 drivers. For a bus driver, if this parameter is NULL, then handles
373 for all the children of Controller are created by this driver.
374 If this parameter is not NULL and the first Device Path Node is
375 not the End of Device Path Node, then only the handle for the
376 child device specified by the first Device Path Node of
377 RemainingDevicePath is created by this driver.
378 If the first Device Path Node of RemainingDevicePath is
379 the End of Device Path Node, no child handle is created by this
382 @retval EFI_SUCCESS The device was started.
383 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
384 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
385 @retval Others The driver failed to start the device.
390 HttpBootIp4DxeDriverBindingStart (
391 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
392 IN EFI_HANDLE ControllerHandle
,
393 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
397 HTTP_BOOT_PRIVATE_DATA
*Private
;
399 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
405 Status
= gBS
->OpenProtocol (
409 This
->DriverBindingHandle
,
411 EFI_OPEN_PROTOCOL_GET_PROTOCOL
414 if (!EFI_ERROR (Status
)) {
415 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id
);
420 // Initialize the private data structure.
422 Private
= AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA
));
423 if (Private
== NULL
) {
424 return EFI_OUT_OF_RESOURCES
;
426 Private
->Signature
= HTTP_BOOT_PRIVATE_DATA_SIGNATURE
;
427 Private
->Controller
= ControllerHandle
;
428 InitializeListHead (&Private
->CacheList
);
430 // Get the NII interface if it exists, it's not required.
432 Status
= gBS
->OpenProtocol (
434 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
435 (VOID
**) &Private
->Nii
,
436 This
->DriverBindingHandle
,
438 EFI_OPEN_PROTOCOL_GET_PROTOCOL
440 if (EFI_ERROR (Status
)) {
445 // Open Device Path Protocol to prepare for appending IP and URI node.
447 Status
= gBS
->OpenProtocol (
449 &gEfiDevicePathProtocolGuid
,
450 (VOID
**) &Private
->ParentDevicePath
,
451 This
->DriverBindingHandle
,
453 EFI_OPEN_PROTOCOL_GET_PROTOCOL
455 if (EFI_ERROR (Status
)) {
460 // Initialize the HII configuration form.
462 Status
= HttpBootConfigFormInit (Private
);
463 if (EFI_ERROR (Status
)) {
468 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
469 // NIC handle and the private data.
471 Status
= gBS
->InstallProtocolInterface (
474 EFI_NATIVE_INTERFACE
,
477 if (EFI_ERROR (Status
)) {
483 if (Private
->Ip4Nic
!= NULL
) {
485 // Already created before
490 Private
->Ip4Nic
= AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC
));
491 if (Private
->Ip4Nic
== NULL
) {
492 Status
= EFI_OUT_OF_RESOURCES
;
495 Private
->Ip4Nic
->Private
= Private
;
496 Private
->Ip4Nic
->ImageHandle
= This
->DriverBindingHandle
;
497 Private
->Ip4Nic
->Signature
= HTTP_BOOT_VIRTUAL_NIC_SIGNATURE
;
500 // Create DHCP4 child instance.
502 Status
= NetLibCreateServiceChild (
504 This
->DriverBindingHandle
,
505 &gEfiDhcp4ServiceBindingProtocolGuid
,
508 if (EFI_ERROR (Status
)) {
512 Status
= gBS
->OpenProtocol (
514 &gEfiDhcp4ProtocolGuid
,
515 (VOID
**) &Private
->Dhcp4
,
516 This
->DriverBindingHandle
,
518 EFI_OPEN_PROTOCOL_BY_DRIVER
520 if (EFI_ERROR (Status
)) {
525 // Get the Ip4Config2 protocol, it's required to configure the default gateway address.
527 Status
= gBS
->OpenProtocol (
529 &gEfiIp4Config2ProtocolGuid
,
530 (VOID
**) &Private
->Ip4Config2
,
531 This
->DriverBindingHandle
,
533 EFI_OPEN_PROTOCOL_GET_PROTOCOL
535 if (EFI_ERROR (Status
)) {
540 // Append IPv4 device path node.
542 Node
= AllocateZeroPool (sizeof (IPv4_DEVICE_PATH
));
544 Status
= EFI_OUT_OF_RESOURCES
;
547 Node
->Ipv4
.Header
.Type
= MESSAGING_DEVICE_PATH
;
548 Node
->Ipv4
.Header
.SubType
= MSG_IPv4_DP
;
549 SetDevicePathNodeLength (Node
, sizeof (IPv4_DEVICE_PATH
));
550 Node
->Ipv4
.StaticIpAddress
= FALSE
;
551 DevicePath
= AppendDevicePathNode (Private
->ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
553 if (DevicePath
== NULL
) {
554 Status
= EFI_OUT_OF_RESOURCES
;
559 // Append URI device path node.
561 Node
= AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL
));
563 Status
= EFI_OUT_OF_RESOURCES
;
566 Node
->DevPath
.Type
= MESSAGING_DEVICE_PATH
;
567 Node
->DevPath
.SubType
= MSG_URI_DP
;
568 SetDevicePathNodeLength (Node
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
569 Private
->Ip4Nic
->DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
571 FreePool (DevicePath
);
572 if (Private
->Ip4Nic
->DevicePath
== NULL
) {
573 Status
= EFI_OUT_OF_RESOURCES
;
578 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
580 CopyMem (&Private
->Ip4Nic
->LoadFile
, &gHttpBootDxeLoadFile
, sizeof (EFI_LOAD_FILE_PROTOCOL
));
581 Status
= gBS
->InstallMultipleProtocolInterfaces (
582 &Private
->Ip4Nic
->Controller
,
583 &gEfiLoadFileProtocolGuid
,
584 &Private
->Ip4Nic
->LoadFile
,
585 &gEfiDevicePathProtocolGuid
,
586 Private
->Ip4Nic
->DevicePath
,
589 if (EFI_ERROR (Status
)) {
594 // Open the Caller Id child to setup a parent-child relationship between
595 // real NIC handle and the HTTP boot Ipv4 NIC handle.
597 Status
= gBS
->OpenProtocol (
601 This
->DriverBindingHandle
,
602 Private
->Ip4Nic
->Controller
,
603 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
605 if (EFI_ERROR (Status
)) {
612 if (Private
!= NULL
) {
614 gBS
->UninstallProtocolInterface (
621 HttpBootDestroyIp4Children (This
, Private
);
622 HttpBootConfigFormUnload (Private
);
634 Stops a device controller or a bus controller.
636 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
637 As a result, much of the error checking on the parameters to Stop() has been moved
638 into this common boot service. It is legal to call Stop() from other locations,
639 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
640 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
641 same driver's Start() function.
642 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
643 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
644 Start() function, and the Start() function must have called OpenProtocol() on
645 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
647 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
648 @param[in] ControllerHandle A handle to the device being stopped. The handle must
649 support a bus specific I/O protocol for the driver
650 to use to stop the device.
651 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
652 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
653 if NumberOfChildren is 0.
655 @retval EFI_SUCCESS The device was stopped.
656 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
661 HttpBootIp4DxeDriverBindingStop (
662 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
663 IN EFI_HANDLE ControllerHandle
,
664 IN UINTN NumberOfChildren
,
665 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
669 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
670 HTTP_BOOT_PRIVATE_DATA
*Private
;
671 EFI_HANDLE NicHandle
;
675 // Try to get the Load File Protocol from the controller handle.
677 Status
= gBS
->OpenProtocol (
679 &gEfiLoadFileProtocolGuid
,
681 This
->DriverBindingHandle
,
683 EFI_OPEN_PROTOCOL_GET_PROTOCOL
685 if (EFI_ERROR (Status
)) {
687 // If failed, try to find the NIC handle for this controller.
689 NicHandle
= HttpBootGetNicByIp4Children (ControllerHandle
);
690 if (NicHandle
== NULL
) {
695 // Try to retrieve the private data by the Caller Id Guid.
697 Status
= gBS
->OpenProtocol (
701 This
->DriverBindingHandle
,
703 EFI_OPEN_PROTOCOL_GET_PROTOCOL
705 if (EFI_ERROR (Status
)) {
708 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id
);
710 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile
);
711 NicHandle
= Private
->Controller
;
715 // Disable the HTTP boot function.
717 Status
= HttpBootStop (Private
);
718 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
723 // Destroy all child instance and uninstall protocol interface.
725 HttpBootDestroyIp4Children (This
, Private
);
727 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
729 // Release the cached data.
731 HttpBootFreeCacheList (Private
);
734 // Unload the config form.
736 HttpBootConfigFormUnload (Private
);
738 gBS
->UninstallProtocolInterface (
751 Tests to see if this driver supports a given controller. If a child device is provided,
752 it further tests to see if this driver supports creating a handle for the specified child device.
754 This function checks to see if the driver specified by This supports the device specified by
755 ControllerHandle. Drivers will typically use the device path attached to
756 ControllerHandle and/or the services from the bus I/O abstraction attached to
757 ControllerHandle to determine if the driver supports ControllerHandle. This function
758 may be called many times during platform initialization. In order to reduce boot times, the tests
759 performed by this function must be very small, and take as little time as possible to execute. This
760 function must not change the state of any hardware devices, and this function must be aware that the
761 device specified by ControllerHandle may already be managed by the same driver or a
762 different driver. This function must match its calls to AllocatePages() with FreePages(),
763 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
764 Because ControllerHandle may have been previously started by the same driver, if a protocol is
765 already in the opened state, then it must not be closed with CloseProtocol(). This is required
766 to guarantee the state of ControllerHandle is not modified by this function.
768 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
769 @param[in] ControllerHandle The handle of the controller to test. This handle
770 must support a protocol interface that supplies
771 an I/O abstraction to the driver.
772 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
773 parameter is ignored by device drivers, and is optional for bus
774 drivers. For bus drivers, if this parameter is not NULL, then
775 the bus driver must determine if the bus controller specified
776 by ControllerHandle and the child controller specified
777 by RemainingDevicePath are both supported by this
780 @retval EFI_SUCCESS The device specified by ControllerHandle and
781 RemainingDevicePath is supported by the driver specified by This.
782 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
783 RemainingDevicePath is already being managed by the driver
785 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
786 RemainingDevicePath is already being managed by a different
787 driver or an application that requires exclusive access.
788 Currently not implemented.
789 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
790 RemainingDevicePath is not supported by the driver specified by This.
794 HttpBootIp6DxeDriverBindingSupported (
795 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
796 IN EFI_HANDLE ControllerHandle
,
797 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
803 // Try to open the DHCP6, HTTP and Device Path protocol.
805 Status
= gBS
->OpenProtocol (
807 &gEfiDhcp6ServiceBindingProtocolGuid
,
809 This
->DriverBindingHandle
,
811 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
813 if (EFI_ERROR (Status
)) {
817 Status
= gBS
->OpenProtocol (
819 &gEfiHttpServiceBindingProtocolGuid
,
821 This
->DriverBindingHandle
,
823 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
825 if (EFI_ERROR (Status
)) {
829 Status
= gBS
->OpenProtocol (
831 &gEfiDevicePathProtocolGuid
,
833 This
->DriverBindingHandle
,
835 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
843 Starts a device controller or a bus controller.
845 The Start() function is designed to be invoked from the EFI boot service ConnectController().
846 As a result, much of the error checking on the parameters to Start() has been moved into this
847 common boot service. It is legal to call Start() from other locations,
848 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
849 1. ControllerHandle must be a valid EFI_HANDLE.
850 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
851 EFI_DEVICE_PATH_PROTOCOL.
852 3. Prior to calling Start(), the Supported() function for the driver specified by This must
853 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
855 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
856 @param[in] ControllerHandle The handle of the controller to start. This handle
857 must support a protocol interface that supplies
858 an I/O abstraction to the driver.
859 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
860 parameter is ignored by device drivers, and is optional for bus
861 drivers. For a bus driver, if this parameter is NULL, then handles
862 for all the children of Controller are created by this driver.
863 If this parameter is not NULL and the first Device Path Node is
864 not the End of Device Path Node, then only the handle for the
865 child device specified by the first Device Path Node of
866 RemainingDevicePath is created by this driver.
867 If the first Device Path Node of RemainingDevicePath is
868 the End of Device Path Node, no child handle is created by this
871 @retval EFI_SUCCESS The device was started.
872 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
873 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
874 @retval Others The driver failed to start the device.
879 HttpBootIp6DxeDriverBindingStart (
880 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
881 IN EFI_HANDLE ControllerHandle
,
882 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
886 HTTP_BOOT_PRIVATE_DATA
*Private
;
888 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
890 BOOLEAN Ipv6Available
;
895 Status
= gBS
->OpenProtocol (
899 This
->DriverBindingHandle
,
901 EFI_OPEN_PROTOCOL_GET_PROTOCOL
904 if (!EFI_ERROR (Status
)) {
905 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id
);
910 // Initialize the private data structure.
912 Private
= AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA
));
913 if (Private
== NULL
) {
914 return EFI_OUT_OF_RESOURCES
;
916 Private
->Signature
= HTTP_BOOT_PRIVATE_DATA_SIGNATURE
;
917 Private
->Controller
= ControllerHandle
;
918 InitializeListHead (&Private
->CacheList
);
920 // Get the NII interface if it exists, it's not required.
922 Status
= gBS
->OpenProtocol (
924 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
925 (VOID
**) &Private
->Nii
,
926 This
->DriverBindingHandle
,
928 EFI_OPEN_PROTOCOL_GET_PROTOCOL
930 if (EFI_ERROR (Status
)) {
935 // Open Device Path Protocol to prepare for appending IP and URI node.
937 Status
= gBS
->OpenProtocol (
939 &gEfiDevicePathProtocolGuid
,
940 (VOID
**) &Private
->ParentDevicePath
,
941 This
->DriverBindingHandle
,
943 EFI_OPEN_PROTOCOL_GET_PROTOCOL
945 if (EFI_ERROR (Status
)) {
950 // Initialize the HII configuration form.
952 Status
= HttpBootConfigFormInit (Private
);
953 if (EFI_ERROR (Status
)) {
958 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
959 // NIC handle and the private data.
961 Status
= gBS
->InstallProtocolInterface (
964 EFI_NATIVE_INTERFACE
,
967 if (EFI_ERROR (Status
)) {
974 // Set IPv6 available flag.
976 Status
= HttpBootCheckIpv6Support (Private
, &Ipv6Available
);
977 if (EFI_ERROR (Status
)) {
979 // Fail to get the data whether UNDI supports IPv6.
980 // Set default value to TRUE.
982 Ipv6Available
= TRUE
;
985 if (!Ipv6Available
) {
986 Status
= EFI_UNSUPPORTED
;
990 if (Private
->Ip6Nic
!= NULL
) {
992 // Already created before
997 Private
->Ip6Nic
= AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC
));
998 if (Private
->Ip6Nic
== NULL
) {
999 Status
= EFI_OUT_OF_RESOURCES
;
1002 Private
->Ip6Nic
->Private
= Private
;
1003 Private
->Ip6Nic
->ImageHandle
= This
->DriverBindingHandle
;
1004 Private
->Ip6Nic
->Signature
= HTTP_BOOT_VIRTUAL_NIC_SIGNATURE
;
1007 // Create Dhcp6 child and open Dhcp6 protocol
1008 Status
= NetLibCreateServiceChild (
1010 This
->DriverBindingHandle
,
1011 &gEfiDhcp6ServiceBindingProtocolGuid
,
1012 &Private
->Dhcp6Child
1014 if (EFI_ERROR (Status
)) {
1018 Status
= gBS
->OpenProtocol (
1019 Private
->Dhcp6Child
,
1020 &gEfiDhcp6ProtocolGuid
,
1021 (VOID
**) &Private
->Dhcp6
,
1022 This
->DriverBindingHandle
,
1024 EFI_OPEN_PROTOCOL_BY_DRIVER
1026 if (EFI_ERROR (Status
)) {
1031 // Create Ip6 child and open Ip6 protocol for background ICMP packets.
1033 Status
= NetLibCreateServiceChild (
1035 This
->DriverBindingHandle
,
1036 &gEfiIp6ServiceBindingProtocolGuid
,
1039 if (EFI_ERROR (Status
)) {
1043 Status
= gBS
->OpenProtocol (
1045 &gEfiIp6ProtocolGuid
,
1046 (VOID
**) &Private
->Ip6
,
1047 This
->DriverBindingHandle
,
1049 EFI_OPEN_PROTOCOL_BY_DRIVER
1051 if (EFI_ERROR (Status
)) {
1056 // Locate Ip6Config protocol, it's required to configure the default gateway address.
1058 Status
= gBS
->OpenProtocol (
1060 &gEfiIp6ConfigProtocolGuid
,
1061 (VOID
**) &Private
->Ip6Config
,
1062 This
->DriverBindingHandle
,
1064 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1066 if (EFI_ERROR (Status
)) {
1071 // Append IPv6 device path node.
1073 Node
= AllocateZeroPool (sizeof (IPv6_DEVICE_PATH
));
1075 Status
= EFI_OUT_OF_RESOURCES
;
1078 Node
->Ipv6
.Header
.Type
= MESSAGING_DEVICE_PATH
;
1079 Node
->Ipv6
.Header
.SubType
= MSG_IPv6_DP
;
1080 Node
->Ipv6
.PrefixLength
= IP6_PREFIX_LENGTH
;
1081 SetDevicePathNodeLength (Node
, sizeof (IPv6_DEVICE_PATH
));
1082 DevicePath
= AppendDevicePathNode(Private
->ParentDevicePath
, (EFI_DEVICE_PATH
*) Node
);
1084 if (DevicePath
== NULL
) {
1085 Status
= EFI_OUT_OF_RESOURCES
;
1090 // Append URI device path node.
1092 Node
= AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL
));
1094 Status
= EFI_OUT_OF_RESOURCES
;
1097 Node
->DevPath
.Type
= MESSAGING_DEVICE_PATH
;
1098 Node
->DevPath
.SubType
= MSG_URI_DP
;
1099 SetDevicePathNodeLength (Node
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
1100 Private
->Ip6Nic
->DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
1102 FreePool (DevicePath
);
1103 if (Private
->Ip6Nic
->DevicePath
== NULL
) {
1104 Status
= EFI_OUT_OF_RESOURCES
;
1109 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
1111 CopyMem (&Private
->Ip6Nic
->LoadFile
, &gHttpBootDxeLoadFile
, sizeof (Private
->LoadFile
));
1112 Status
= gBS
->InstallMultipleProtocolInterfaces (
1113 &Private
->Ip6Nic
->Controller
,
1114 &gEfiLoadFileProtocolGuid
,
1115 &Private
->Ip6Nic
->LoadFile
,
1116 &gEfiDevicePathProtocolGuid
,
1117 Private
->Ip6Nic
->DevicePath
,
1120 if (EFI_ERROR (Status
)) {
1125 // Open the Caller Id child to setup a parent-child relationship between
1126 // real NIC handle and the HTTP boot child handle.
1128 Status
= gBS
->OpenProtocol (
1132 This
->DriverBindingHandle
,
1133 Private
->Ip6Nic
->Controller
,
1134 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
1136 if (EFI_ERROR (Status
)) {
1143 if (Private
!= NULL
) {
1145 gBS
->UninstallProtocolInterface (
1152 HttpBootDestroyIp6Children(This
, Private
);
1153 HttpBootConfigFormUnload (Private
);
1164 Stops a device controller or a bus controller.
1166 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1167 As a result, much of the error checking on the parameters to Stop() has been moved
1168 into this common boot service. It is legal to call Stop() from other locations,
1169 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1170 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1171 same driver's Start() function.
1172 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1173 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1174 Start() function, and the Start() function must have called OpenProtocol() on
1175 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1177 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1178 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1179 support a bus specific I/O protocol for the driver
1180 to use to stop the device.
1181 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1182 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1183 if NumberOfChildren is 0.
1185 @retval EFI_SUCCESS The device was stopped.
1186 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1191 HttpBootIp6DxeDriverBindingStop (
1192 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1193 IN EFI_HANDLE ControllerHandle
,
1194 IN UINTN NumberOfChildren
,
1195 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1199 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1200 HTTP_BOOT_PRIVATE_DATA
*Private
;
1201 EFI_HANDLE NicHandle
;
1205 // Try to get the Load File Protocol from the controller handle.
1207 Status
= gBS
->OpenProtocol (
1209 &gEfiLoadFileProtocolGuid
,
1210 (VOID
**) &LoadFile
,
1211 This
->DriverBindingHandle
,
1213 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1215 if (EFI_ERROR (Status
)) {
1217 // If failed, try to find the NIC handle for this controller.
1219 NicHandle
= HttpBootGetNicByIp6Children (ControllerHandle
);
1220 if (NicHandle
== NULL
) {
1225 // Try to retrieve the private data by the Caller Id Guid.
1227 Status
= gBS
->OpenProtocol (
1231 This
->DriverBindingHandle
,
1233 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1235 if (EFI_ERROR (Status
)) {
1238 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id
);
1240 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile
);
1241 NicHandle
= Private
->Controller
;
1245 // Disable the HTTP boot function.
1247 Status
= HttpBootStop (Private
);
1248 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
1253 // Destroy all child instance and uninstall protocol interface.
1255 HttpBootDestroyIp6Children (This
, Private
);
1257 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
1259 // Release the cached data.
1261 HttpBootFreeCacheList (Private
);
1264 // Unload the config form.
1266 HttpBootConfigFormUnload (Private
);
1268 gBS
->UninstallProtocolInterface (
1280 This is the declaration of an EFI image entry point. This entry point is
1281 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1282 both device drivers and bus drivers.
1284 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1285 @param[in] SystemTable A pointer to the EFI System Table.
1287 @retval EFI_SUCCESS The operation completed successfully.
1288 @retval Others An unexpected error occurred.
1293 HttpBootDxeDriverEntryPoint (
1294 IN EFI_HANDLE ImageHandle
,
1295 IN EFI_SYSTEM_TABLE
*SystemTable
1301 // Install UEFI Driver Model protocol(s).
1303 Status
= EfiLibInstallDriverBindingComponentName2 (
1306 &gHttpBootIp4DxeDriverBinding
,
1308 &gHttpBootDxeComponentName
,
1309 &gHttpBootDxeComponentName2
1311 if (EFI_ERROR (Status
)) {
1315 Status
= EfiLibInstallDriverBindingComponentName2 (
1318 &gHttpBootIp6DxeDriverBinding
,
1320 &gHttpBootDxeComponentName
,
1321 &gHttpBootDxeComponentName2
1323 if (EFI_ERROR (Status
)) {
1324 EfiLibUninstallDriverBindingComponentName2(
1325 &gHttpBootIp4DxeDriverBinding
,
1326 &gHttpBootDxeComponentName
,
1327 &gHttpBootDxeComponentName2