2 Driver Binding functions implementation for UEFI HTTP boot.
4 Copyright (c) 2015, 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
,
39 Destroy the HTTP child based on IPv4 stack.
41 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
42 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
46 HttpBootDestroyIp4Children (
47 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
48 IN HTTP_BOOT_PRIVATE_DATA
*Private
51 ASSERT (This
!= NULL
);
52 ASSERT (Private
!= NULL
);
54 if (Private
->Dhcp4Child
!= NULL
) {
57 &gEfiDhcp4ProtocolGuid
,
58 This
->DriverBindingHandle
,
62 NetLibDestroyServiceChild (
64 This
->DriverBindingHandle
,
65 &gEfiDhcp4ServiceBindingProtocolGuid
,
70 if (Private
->HttpCreated
) {
71 HttpIoDestroyIo (&Private
->HttpIo
);
72 Private
->HttpCreated
= FALSE
;
75 if (Private
->Ip4Nic
!= NULL
) {
80 This
->DriverBindingHandle
,
81 Private
->Ip4Nic
->Controller
84 gBS
->UninstallMultipleProtocolInterfaces (
85 Private
->Ip4Nic
->Controller
,
86 &gEfiLoadFileProtocolGuid
,
87 &Private
->Ip4Nic
->LoadFile
,
88 &gEfiDevicePathProtocolGuid
,
89 Private
->Ip4Nic
->DevicePath
,
92 FreePool (Private
->Ip4Nic
);
93 Private
->Ip4Nic
= NULL
;
99 Destroy the HTTP child based on IPv6 stack.
101 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
102 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
106 HttpBootDestroyIp6Children (
107 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
108 IN HTTP_BOOT_PRIVATE_DATA
*Private
111 ASSERT (This
!= NULL
);
112 ASSERT (Private
!= NULL
);
114 if (Private
->Ip6Child
!= NULL
) {
117 &gEfiIp6ProtocolGuid
,
118 This
->DriverBindingHandle
,
122 NetLibDestroyServiceChild (
124 This
->DriverBindingHandle
,
125 &gEfiIp6ServiceBindingProtocolGuid
,
130 if (Private
->Dhcp6Child
!= NULL
) {
133 &gEfiDhcp6ProtocolGuid
,
134 This
->DriverBindingHandle
,
138 NetLibDestroyServiceChild (
140 This
->DriverBindingHandle
,
141 &gEfiDhcp6ServiceBindingProtocolGuid
,
146 if (Private
->HttpCreated
) {
147 HttpIoDestroyIo(&Private
->HttpIo
);
148 Private
->HttpCreated
= FALSE
;
151 if (Private
->Ip6Nic
!= NULL
) {
156 This
->DriverBindingHandle
,
157 Private
->Ip6Nic
->Controller
160 gBS
->UninstallMultipleProtocolInterfaces (
161 Private
->Ip6Nic
->Controller
,
162 &gEfiLoadFileProtocolGuid
,
163 &Private
->Ip6Nic
->LoadFile
,
164 &gEfiDevicePathProtocolGuid
,
165 Private
->Ip6Nic
->DevicePath
,
168 FreePool (Private
->Ip6Nic
);
169 Private
->Ip6Nic
= NULL
;
174 Tests to see if this driver supports a given controller. If a child device is provided,
175 it further tests to see if this driver supports creating a handle for the specified child device.
177 This function checks to see if the driver specified by This supports the device specified by
178 ControllerHandle. Drivers will typically use the device path attached to
179 ControllerHandle and/or the services from the bus I/O abstraction attached to
180 ControllerHandle to determine if the driver supports ControllerHandle. This function
181 may be called many times during platform initialization. In order to reduce boot times, the tests
182 performed by this function must be very small, and take as little time as possible to execute. This
183 function must not change the state of any hardware devices, and this function must be aware that the
184 device specified by ControllerHandle may already be managed by the same driver or a
185 different driver. This function must match its calls to AllocatePages() with FreePages(),
186 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
187 Because ControllerHandle may have been previously started by the same driver, if a protocol is
188 already in the opened state, then it must not be closed with CloseProtocol(). This is required
189 to guarantee the state of ControllerHandle is not modified by this function.
191 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
192 @param[in] ControllerHandle The handle of the controller to test. This handle
193 must support a protocol interface that supplies
194 an I/O abstraction to the driver.
195 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
196 parameter is ignored by device drivers, and is optional for bus
197 drivers. For bus drivers, if this parameter is not NULL, then
198 the bus driver must determine if the bus controller specified
199 by ControllerHandle and the child controller specified
200 by RemainingDevicePath are both supported by this
203 @retval EFI_SUCCESS The device specified by ControllerHandle and
204 RemainingDevicePath is supported by the driver specified by This.
205 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
206 RemainingDevicePath is already being managed by the driver
208 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
209 RemainingDevicePath is already being managed by a different
210 driver or an application that requires exclusive access.
211 Currently not implemented.
212 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
213 RemainingDevicePath is not supported by the driver specified by This.
217 HttpBootIp4DxeDriverBindingSupported (
218 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
219 IN EFI_HANDLE ControllerHandle
,
220 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
226 // Try to open the DHCP4, HTTP4 and Device Path protocol.
228 Status
= gBS
->OpenProtocol (
230 &gEfiDhcp4ServiceBindingProtocolGuid
,
232 This
->DriverBindingHandle
,
234 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
236 if (EFI_ERROR (Status
)) {
240 Status
= gBS
->OpenProtocol (
242 &gEfiHttpServiceBindingProtocolGuid
,
244 This
->DriverBindingHandle
,
246 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
248 if (EFI_ERROR (Status
)) {
252 Status
= gBS
->OpenProtocol (
254 &gEfiDevicePathProtocolGuid
,
256 This
->DriverBindingHandle
,
258 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
266 Starts a device controller or a bus controller.
268 The Start() function is designed to be invoked from the EFI boot service ConnectController().
269 As a result, much of the error checking on the parameters to Start() has been moved into this
270 common boot service. It is legal to call Start() from other locations,
271 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
272 1. ControllerHandle must be a valid EFI_HANDLE.
273 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
274 EFI_DEVICE_PATH_PROTOCOL.
275 3. Prior to calling Start(), the Supported() function for the driver specified by This must
276 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
278 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
279 @param[in] ControllerHandle The handle of the controller to start. This handle
280 must support a protocol interface that supplies
281 an I/O abstraction to the driver.
282 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
283 parameter is ignored by device drivers, and is optional for bus
284 drivers. For a bus driver, if this parameter is NULL, then handles
285 for all the children of Controller are created by this driver.
286 If this parameter is not NULL and the first Device Path Node is
287 not the End of Device Path Node, then only the handle for the
288 child device specified by the first Device Path Node of
289 RemainingDevicePath is created by this driver.
290 If the first Device Path Node of RemainingDevicePath is
291 the End of Device Path Node, no child handle is created by this
294 @retval EFI_SUCCESS The device was started.
295 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
296 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
297 @retval Others The driver failded to start the device.
302 HttpBootIp4DxeDriverBindingStart (
303 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
304 IN EFI_HANDLE ControllerHandle
,
305 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
309 HTTP_BOOT_PRIVATE_DATA
*Private
;
311 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
314 Status
= gBS
->OpenProtocol (
318 This
->DriverBindingHandle
,
320 EFI_OPEN_PROTOCOL_GET_PROTOCOL
323 if (!EFI_ERROR (Status
)) {
324 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id
);
327 // Initialize the private data structure.
329 Private
= AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA
));
330 if (Private
== NULL
) {
331 return EFI_OUT_OF_RESOURCES
;
333 Private
->Signature
= HTTP_BOOT_PRIVATE_DATA_SIGNATURE
;
334 Private
->Controller
= ControllerHandle
;
335 Private
->Image
= This
->ImageHandle
;
336 InitializeListHead (&Private
->CacheList
);
338 // Get the NII interface if it exists, it's not required.
340 Status
= gBS
->OpenProtocol (
342 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
343 (VOID
**) &Private
->Nii
,
344 This
->DriverBindingHandle
,
346 EFI_OPEN_PROTOCOL_GET_PROTOCOL
348 if (EFI_ERROR (Status
)) {
353 // Open Device Path Protocol to prepare for appending IP and URI node.
355 Status
= gBS
->OpenProtocol (
357 &gEfiDevicePathProtocolGuid
,
358 (VOID
**) &Private
->ParentDevicePath
,
359 This
->DriverBindingHandle
,
361 EFI_OPEN_PROTOCOL_GET_PROTOCOL
363 if (EFI_ERROR (Status
)) {
368 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
369 // NIC handle and the private data.
371 Status
= gBS
->InstallProtocolInterface (
374 EFI_NATIVE_INTERFACE
,
377 if (EFI_ERROR (Status
)) {
383 if (Private
->Ip4Nic
!= NULL
) {
385 // Already created before
390 Private
->Ip4Nic
= AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC
));
391 if (Private
->Ip4Nic
== NULL
) {
392 return EFI_OUT_OF_RESOURCES
;
394 Private
->Ip4Nic
->Private
= Private
;
395 Private
->Ip4Nic
->Signature
= HTTP_BOOT_VIRTUAL_NIC_SIGNATURE
;
398 // Create DHCP4 child instance.
400 Status
= NetLibCreateServiceChild (
402 This
->DriverBindingHandle
,
403 &gEfiDhcp4ServiceBindingProtocolGuid
,
406 if (EFI_ERROR (Status
)) {
410 Status
= gBS
->OpenProtocol (
412 &gEfiDhcp4ProtocolGuid
,
413 (VOID
**) &Private
->Dhcp4
,
414 This
->DriverBindingHandle
,
416 EFI_OPEN_PROTOCOL_BY_DRIVER
418 if (EFI_ERROR (Status
)) {
423 // Get the Ip4Config2 protocol, it's required to configure the default gateway address.
425 Status
= gBS
->OpenProtocol (
427 &gEfiIp4Config2ProtocolGuid
,
428 (VOID
**) &Private
->Ip4Config2
,
429 This
->DriverBindingHandle
,
431 EFI_OPEN_PROTOCOL_GET_PROTOCOL
433 if (EFI_ERROR (Status
)) {
438 // Append IPv4 device path node.
440 Node
= AllocateZeroPool (sizeof (IPv4_DEVICE_PATH
));
442 Status
= EFI_OUT_OF_RESOURCES
;
445 Node
->Ipv4
.Header
.Type
= MESSAGING_DEVICE_PATH
;
446 Node
->Ipv4
.Header
.SubType
= MSG_IPv4_DP
;
447 SetDevicePathNodeLength (Node
, sizeof (IPv4_DEVICE_PATH
));
448 Node
->Ipv4
.StaticIpAddress
= FALSE
;
449 DevicePath
= AppendDevicePathNode (Private
->ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
451 if (DevicePath
== NULL
) {
452 Status
= EFI_OUT_OF_RESOURCES
;
457 // Append URI device path node.
459 Node
= AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL
));
461 Status
= EFI_OUT_OF_RESOURCES
;
464 Node
->DevPath
.Type
= MESSAGING_DEVICE_PATH
;
465 Node
->DevPath
.SubType
= MSG_URI_DP
;
466 SetDevicePathNodeLength (Node
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
467 Private
->Ip4Nic
->DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
469 FreePool (DevicePath
);
470 if (Private
->Ip4Nic
->DevicePath
== NULL
) {
471 Status
= EFI_OUT_OF_RESOURCES
;
476 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
478 CopyMem (&Private
->Ip4Nic
->LoadFile
, &gHttpBootDxeLoadFile
, sizeof (EFI_LOAD_FILE_PROTOCOL
));
479 Status
= gBS
->InstallMultipleProtocolInterfaces (
480 &Private
->Ip4Nic
->Controller
,
481 &gEfiLoadFileProtocolGuid
,
482 &Private
->Ip4Nic
->LoadFile
,
483 &gEfiDevicePathProtocolGuid
,
484 Private
->Ip4Nic
->DevicePath
,
487 if (EFI_ERROR (Status
)) {
492 // Open the Caller Id child to setup a parent-child relationship between
493 // real NIC handle and the HTTP boot Ipv4 NIC handle.
495 Status
= gBS
->OpenProtocol (
499 This
->DriverBindingHandle
,
500 Private
->Ip4Nic
->Controller
,
501 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
503 if (EFI_ERROR (Status
)) {
512 HttpBootDestroyIp4Children (This
, Private
);
520 Stops a device controller or a bus controller.
522 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
523 As a result, much of the error checking on the parameters to Stop() has been moved
524 into this common boot service. It is legal to call Stop() from other locations,
525 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
526 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
527 same driver's Start() function.
528 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
529 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
530 Start() function, and the Start() function must have called OpenProtocol() on
531 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
533 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
534 @param[in] ControllerHandle A handle to the device being stopped. The handle must
535 support a bus specific I/O protocol for the driver
536 to use to stop the device.
537 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
538 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
539 if NumberOfChildren is 0.
541 @retval EFI_SUCCESS The device was stopped.
542 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
547 HttpBootIp4DxeDriverBindingStop (
548 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
549 IN EFI_HANDLE ControllerHandle
,
550 IN UINTN NumberOfChildren
,
551 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
555 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
556 HTTP_BOOT_PRIVATE_DATA
*Private
;
557 EFI_HANDLE NicHandle
;
561 // Try to get the Load File Protocol from the controller handle.
563 Status
= gBS
->OpenProtocol (
565 &gEfiLoadFileProtocolGuid
,
567 This
->DriverBindingHandle
,
569 EFI_OPEN_PROTOCOL_GET_PROTOCOL
571 if (EFI_ERROR (Status
)) {
573 // If failed, try to find the NIC handle for this controller.
575 NicHandle
= HttpBootGetNicByIp4Children (ControllerHandle
);
576 if (NicHandle
== NULL
) {
581 // Try to retrieve the private data by the Caller Id Guid.
583 Status
= gBS
->OpenProtocol (
587 This
->DriverBindingHandle
,
589 EFI_OPEN_PROTOCOL_GET_PROTOCOL
591 if (EFI_ERROR (Status
)) {
594 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id
);
596 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile
);
597 NicHandle
= Private
->Controller
;
601 // Disable the HTTP boot function.
603 Status
= HttpBootStop (Private
);
604 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
609 // Destory all child instance and uninstall protocol interface.
611 HttpBootDestroyIp4Children (This
, Private
);
613 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
615 // Release the cached data.
617 HttpBootFreeCacheList (Private
);
619 gBS
->UninstallProtocolInterface (
632 Tests to see if this driver supports a given controller. If a child device is provided,
633 it further tests to see if this driver supports creating a handle for the specified child device.
635 This function checks to see if the driver specified by This supports the device specified by
636 ControllerHandle. Drivers will typically use the device path attached to
637 ControllerHandle and/or the services from the bus I/O abstraction attached to
638 ControllerHandle to determine if the driver supports ControllerHandle. This function
639 may be called many times during platform initialization. In order to reduce boot times, the tests
640 performed by this function must be very small, and take as little time as possible to execute. This
641 function must not change the state of any hardware devices, and this function must be aware that the
642 device specified by ControllerHandle may already be managed by the same driver or a
643 different driver. This function must match its calls to AllocatePages() with FreePages(),
644 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
645 Because ControllerHandle may have been previously started by the same driver, if a protocol is
646 already in the opened state, then it must not be closed with CloseProtocol(). This is required
647 to guarantee the state of ControllerHandle is not modified by this function.
649 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
650 @param[in] ControllerHandle The handle of the controller to test. This handle
651 must support a protocol interface that supplies
652 an I/O abstraction to the driver.
653 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
654 parameter is ignored by device drivers, and is optional for bus
655 drivers. For bus drivers, if this parameter is not NULL, then
656 the bus driver must determine if the bus controller specified
657 by ControllerHandle and the child controller specified
658 by RemainingDevicePath are both supported by this
661 @retval EFI_SUCCESS The device specified by ControllerHandle and
662 RemainingDevicePath is supported by the driver specified by This.
663 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
664 RemainingDevicePath is already being managed by the driver
666 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
667 RemainingDevicePath is already being managed by a different
668 driver or an application that requires exclusive access.
669 Currently not implemented.
670 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
671 RemainingDevicePath is not supported by the driver specified by This.
675 HttpBootIp6DxeDriverBindingSupported (
676 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
677 IN EFI_HANDLE ControllerHandle
,
678 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
684 // Try to open the DHCP6, HTTP and Device Path protocol.
686 Status
= gBS
->OpenProtocol (
688 &gEfiDhcp6ServiceBindingProtocolGuid
,
690 This
->DriverBindingHandle
,
692 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
694 if (EFI_ERROR (Status
)) {
698 Status
= gBS
->OpenProtocol (
700 &gEfiHttpServiceBindingProtocolGuid
,
702 This
->DriverBindingHandle
,
704 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
706 if (EFI_ERROR (Status
)) {
710 Status
= gBS
->OpenProtocol (
712 &gEfiDevicePathProtocolGuid
,
714 This
->DriverBindingHandle
,
716 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
724 Starts a device controller or a bus controller.
726 The Start() function is designed to be invoked from the EFI boot service ConnectController().
727 As a result, much of the error checking on the parameters to Start() has been moved into this
728 common boot service. It is legal to call Start() from other locations,
729 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
730 1. ControllerHandle must be a valid EFI_HANDLE.
731 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
732 EFI_DEVICE_PATH_PROTOCOL.
733 3. Prior to calling Start(), the Supported() function for the driver specified by This must
734 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
736 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
737 @param[in] ControllerHandle The handle of the controller to start. This handle
738 must support a protocol interface that supplies
739 an I/O abstraction to the driver.
740 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
741 parameter is ignored by device drivers, and is optional for bus
742 drivers. For a bus driver, if this parameter is NULL, then handles
743 for all the children of Controller are created by this driver.
744 If this parameter is not NULL and the first Device Path Node is
745 not the End of Device Path Node, then only the handle for the
746 child device specified by the first Device Path Node of
747 RemainingDevicePath is created by this driver.
748 If the first Device Path Node of RemainingDevicePath is
749 the End of Device Path Node, no child handle is created by this
752 @retval EFI_SUCCESS The device was started.
753 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
754 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
755 @retval Others The driver failded to start the device.
760 HttpBootIp6DxeDriverBindingStart (
761 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
762 IN EFI_HANDLE ControllerHandle
,
763 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
767 HTTP_BOOT_PRIVATE_DATA
*Private
;
769 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
772 Status
= gBS
->OpenProtocol (
776 This
->DriverBindingHandle
,
778 EFI_OPEN_PROTOCOL_GET_PROTOCOL
781 if (!EFI_ERROR (Status
)) {
782 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id
);
785 // Initialize the private data structure.
787 Private
= AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA
));
788 if (Private
== NULL
) {
789 return EFI_OUT_OF_RESOURCES
;
791 Private
->Signature
= HTTP_BOOT_PRIVATE_DATA_SIGNATURE
;
792 Private
->Controller
= ControllerHandle
;
793 Private
->Image
= This
->ImageHandle
;
794 InitializeListHead (&Private
->CacheList
);
796 // Get the NII interface if it exists, it's not required.
798 Status
= gBS
->OpenProtocol (
800 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
801 (VOID
**) &Private
->Nii
,
802 This
->DriverBindingHandle
,
804 EFI_OPEN_PROTOCOL_GET_PROTOCOL
806 if (EFI_ERROR (Status
)) {
811 // Open Device Path Protocol to prepare for appending IP and URI node.
813 Status
= gBS
->OpenProtocol (
815 &gEfiDevicePathProtocolGuid
,
816 (VOID
**) &Private
->ParentDevicePath
,
817 This
->DriverBindingHandle
,
819 EFI_OPEN_PROTOCOL_GET_PROTOCOL
821 if (EFI_ERROR (Status
)) {
826 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
827 // NIC handle and the private data.
829 Status
= gBS
->InstallProtocolInterface (
832 EFI_NATIVE_INTERFACE
,
835 if (EFI_ERROR (Status
)) {
841 if (Private
->Ip6Nic
!= NULL
) {
843 // Already created before
848 Private
->Ip6Nic
= AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC
));
849 if (Private
->Ip6Nic
== NULL
) {
850 return EFI_OUT_OF_RESOURCES
;
852 Private
->Ip6Nic
->Private
= Private
;
853 Private
->Ip6Nic
->Signature
= HTTP_BOOT_VIRTUAL_NIC_SIGNATURE
;
856 // Create Dhcp6 child and open Dhcp6 protocol
857 Status
= NetLibCreateServiceChild (
859 This
->DriverBindingHandle
,
860 &gEfiDhcp6ServiceBindingProtocolGuid
,
863 if (EFI_ERROR (Status
)) {
867 Status
= gBS
->OpenProtocol (
869 &gEfiDhcp6ProtocolGuid
,
870 (VOID
**) &Private
->Dhcp6
,
871 This
->DriverBindingHandle
,
873 EFI_OPEN_PROTOCOL_BY_DRIVER
875 if (EFI_ERROR (Status
)) {
880 // Create Ip6 child and open Ip6 protocol for background ICMP packets.
882 Status
= NetLibCreateServiceChild (
884 This
->DriverBindingHandle
,
885 &gEfiIp6ServiceBindingProtocolGuid
,
888 if (EFI_ERROR (Status
)) {
892 Status
= gBS
->OpenProtocol (
894 &gEfiIp6ProtocolGuid
,
895 (VOID
**) &Private
->Ip6
,
896 This
->DriverBindingHandle
,
898 EFI_OPEN_PROTOCOL_BY_DRIVER
900 if (EFI_ERROR (Status
)) {
905 // Locate Ip6Config protocol, it's required to configure the default gateway address.
907 Status
= gBS
->OpenProtocol (
909 &gEfiIp6ConfigProtocolGuid
,
910 (VOID
**) &Private
->Ip6Config
,
911 This
->DriverBindingHandle
,
913 EFI_OPEN_PROTOCOL_GET_PROTOCOL
915 if (EFI_ERROR (Status
)) {
920 // Append IPv6 device path node.
922 Node
= AllocateZeroPool (sizeof (IPv6_DEVICE_PATH
));
924 Status
= EFI_OUT_OF_RESOURCES
;
927 Node
->Ipv6
.Header
.Type
= MESSAGING_DEVICE_PATH
;
928 Node
->Ipv6
.Header
.SubType
= MSG_IPv6_DP
;
929 Node
->Ipv6
.PrefixLength
= IP6_PREFIX_LENGTH
;
930 SetDevicePathNodeLength (Node
, sizeof (IPv6_DEVICE_PATH
));
931 DevicePath
= AppendDevicePathNode(Private
->ParentDevicePath
, (EFI_DEVICE_PATH
*) Node
);
933 if (DevicePath
== NULL
) {
934 Status
= EFI_OUT_OF_RESOURCES
;
939 // Append URI device path node.
941 Node
= AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL
));
943 Status
= EFI_OUT_OF_RESOURCES
;
946 Node
->DevPath
.Type
= MESSAGING_DEVICE_PATH
;
947 Node
->DevPath
.SubType
= MSG_URI_DP
;
948 SetDevicePathNodeLength (Node
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
949 Private
->Ip6Nic
->DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
951 FreePool (DevicePath
);
952 if (Private
->Ip6Nic
->DevicePath
== NULL
) {
953 Status
= EFI_OUT_OF_RESOURCES
;
958 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
960 CopyMem (&Private
->Ip6Nic
->LoadFile
, &gHttpBootDxeLoadFile
, sizeof (Private
->LoadFile
));
961 Status
= gBS
->InstallMultipleProtocolInterfaces (
962 &Private
->Ip6Nic
->Controller
,
963 &gEfiLoadFileProtocolGuid
,
964 &Private
->Ip6Nic
->LoadFile
,
965 &gEfiDevicePathProtocolGuid
,
966 Private
->Ip6Nic
->DevicePath
,
969 if (EFI_ERROR (Status
)) {
974 // Open the Caller Id child to setup a parent-child relationship between
975 // real NIC handle and the HTTP boot child handle.
977 Status
= gBS
->OpenProtocol (
981 This
->DriverBindingHandle
,
982 Private
->Ip6Nic
->Controller
,
983 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
985 if (EFI_ERROR (Status
)) {
993 HttpBootDestroyIp6Children(This
, Private
);
1001 Stops a device controller or a bus controller.
1003 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
1004 As a result, much of the error checking on the parameters to Stop() has been moved
1005 into this common boot service. It is legal to call Stop() from other locations,
1006 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
1007 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
1008 same driver's Start() function.
1009 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
1010 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
1011 Start() function, and the Start() function must have called OpenProtocol() on
1012 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
1014 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
1015 @param[in] ControllerHandle A handle to the device being stopped. The handle must
1016 support a bus specific I/O protocol for the driver
1017 to use to stop the device.
1018 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
1019 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
1020 if NumberOfChildren is 0.
1022 @retval EFI_SUCCESS The device was stopped.
1023 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
1028 HttpBootIp6DxeDriverBindingStop (
1029 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
1030 IN EFI_HANDLE ControllerHandle
,
1031 IN UINTN NumberOfChildren
,
1032 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
1036 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
1037 HTTP_BOOT_PRIVATE_DATA
*Private
;
1038 EFI_HANDLE NicHandle
;
1042 // Try to get the Load File Protocol from the controller handle.
1044 Status
= gBS
->OpenProtocol (
1046 &gEfiLoadFileProtocolGuid
,
1047 (VOID
**) &LoadFile
,
1048 This
->DriverBindingHandle
,
1050 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1052 if (EFI_ERROR (Status
)) {
1054 // If failed, try to find the NIC handle for this controller.
1056 NicHandle
= HttpBootGetNicByIp6Children (ControllerHandle
);
1057 if (NicHandle
== NULL
) {
1062 // Try to retrieve the private data by the Caller Id Guid.
1064 Status
= gBS
->OpenProtocol (
1068 This
->DriverBindingHandle
,
1070 EFI_OPEN_PROTOCOL_GET_PROTOCOL
1072 if (EFI_ERROR (Status
)) {
1075 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id
);
1077 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile
);
1078 NicHandle
= Private
->Controller
;
1082 // Disable the HTTP boot function.
1084 Status
= HttpBootStop (Private
);
1085 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
1090 // Destory all child instance and uninstall protocol interface.
1092 HttpBootDestroyIp6Children (This
, Private
);
1094 if (Private
->Ip4Nic
== NULL
&& Private
->Ip6Nic
== NULL
) {
1096 // Release the cached data.
1098 HttpBootFreeCacheList (Private
);
1100 gBS
->UninstallProtocolInterface (
1112 This is the declaration of an EFI image entry point. This entry point is
1113 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
1114 both device drivers and bus drivers.
1116 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
1117 @param[in] SystemTable A pointer to the EFI System Table.
1119 @retval EFI_SUCCESS The operation completed successfully.
1120 @retval Others An unexpected error occurred.
1125 HttpBootDxeDriverEntryPoint (
1126 IN EFI_HANDLE ImageHandle
,
1127 IN EFI_SYSTEM_TABLE
*SystemTable
1132 // Install UEFI Driver Model protocol(s).
1134 Status
= EfiLibInstallDriverBindingComponentName2 (
1137 &gHttpBootIp4DxeDriverBinding
,
1139 &gHttpBootDxeComponentName
,
1140 &gHttpBootDxeComponentName2
1142 if (EFI_ERROR (Status
)) {
1146 Status
= EfiLibInstallDriverBindingComponentName2 (
1149 &gHttpBootIp6DxeDriverBinding
,
1151 &gHttpBootDxeComponentName
,
1152 &gHttpBootDxeComponentName2
1154 if (EFI_ERROR (Status
)) {
1155 gBS
->UninstallMultipleProtocolInterfaces(
1157 &gEfiDriverBindingProtocolGuid
,
1158 &gHttpBootIp4DxeDriverBinding
,
1159 &gEfiComponentName2ProtocolGuid
,
1160 &gHttpBootDxeComponentName2
,
1161 &gEfiComponentNameProtocolGuid
,
1162 &gHttpBootDxeComponentName
,