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
,
30 Destroy the HTTP child based on IPv4 stack.
32 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.
33 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.
37 HttpBootDestroyIp4Children (
38 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
39 IN HTTP_BOOT_PRIVATE_DATA
*Private
42 ASSERT (This
!= NULL
);
43 ASSERT (Private
!= NULL
);
44 ASSERT (Private
->UsingIpv6
== FALSE
);
46 if (Private
->Dhcp4Child
!= NULL
) {
49 &gEfiDhcp4ProtocolGuid
,
50 This
->DriverBindingHandle
,
54 NetLibDestroyServiceChild (
56 This
->DriverBindingHandle
,
57 &gEfiDhcp4ServiceBindingProtocolGuid
,
62 if (Private
->HttpCreated
) {
63 HttpIoDestroyIo (&Private
->HttpIo
);
64 Private
->HttpCreated
= FALSE
;
70 This
->DriverBindingHandle
,
74 gBS
->UninstallMultipleProtocolInterfaces (
76 &gEfiLoadFileProtocolGuid
,
78 &gEfiDevicePathProtocolGuid
,
83 if (Private
->DevicePath
!= NULL
) {
84 FreePool (Private
->DevicePath
);
85 Private
->DevicePath
= NULL
;
90 Tests to see if this driver supports a given controller. If a child device is provided,
91 it further tests to see if this driver supports creating a handle for the specified child device.
93 This function checks to see if the driver specified by This supports the device specified by
94 ControllerHandle. Drivers will typically use the device path attached to
95 ControllerHandle and/or the services from the bus I/O abstraction attached to
96 ControllerHandle to determine if the driver supports ControllerHandle. This function
97 may be called many times during platform initialization. In order to reduce boot times, the tests
98 performed by this function must be very small, and take as little time as possible to execute. This
99 function must not change the state of any hardware devices, and this function must be aware that the
100 device specified by ControllerHandle may already be managed by the same driver or a
101 different driver. This function must match its calls to AllocatePages() with FreePages(),
102 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
103 Because ControllerHandle may have been previously started by the same driver, if a protocol is
104 already in the opened state, then it must not be closed with CloseProtocol(). This is required
105 to guarantee the state of ControllerHandle is not modified by this function.
107 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
108 @param[in] ControllerHandle The handle of the controller to test. This handle
109 must support a protocol interface that supplies
110 an I/O abstraction to the driver.
111 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
112 parameter is ignored by device drivers, and is optional for bus
113 drivers. For bus drivers, if this parameter is not NULL, then
114 the bus driver must determine if the bus controller specified
115 by ControllerHandle and the child controller specified
116 by RemainingDevicePath are both supported by this
119 @retval EFI_SUCCESS The device specified by ControllerHandle and
120 RemainingDevicePath is supported by the driver specified by This.
121 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
122 RemainingDevicePath is already being managed by the driver
124 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
125 RemainingDevicePath is already being managed by a different
126 driver or an application that requires exclusive access.
127 Currently not implemented.
128 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
129 RemainingDevicePath is not supported by the driver specified by This.
133 HttpBootIp4DxeDriverBindingSupported (
134 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
135 IN EFI_HANDLE ControllerHandle
,
136 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
142 // Try to open the DHCP4, HTTP4 and Device Path protocol.
144 Status
= gBS
->OpenProtocol (
146 &gEfiDhcp4ServiceBindingProtocolGuid
,
148 This
->DriverBindingHandle
,
150 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
152 if (EFI_ERROR (Status
)) {
156 Status
= gBS
->OpenProtocol (
158 &gEfiHttpServiceBindingProtocolGuid
,
160 This
->DriverBindingHandle
,
162 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
164 if (EFI_ERROR (Status
)) {
168 Status
= gBS
->OpenProtocol (
170 &gEfiDevicePathProtocolGuid
,
172 This
->DriverBindingHandle
,
174 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
182 Starts a device controller or a bus controller.
184 The Start() function is designed to be invoked from the EFI boot service ConnectController().
185 As a result, much of the error checking on the parameters to Start() has been moved into this
186 common boot service. It is legal to call Start() from other locations,
187 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
188 1. ControllerHandle must be a valid EFI_HANDLE.
189 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
190 EFI_DEVICE_PATH_PROTOCOL.
191 3. Prior to calling Start(), the Supported() function for the driver specified by This must
192 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
194 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
195 @param[in] ControllerHandle The handle of the controller to start. This handle
196 must support a protocol interface that supplies
197 an I/O abstraction to the driver.
198 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
199 parameter is ignored by device drivers, and is optional for bus
200 drivers. For a bus driver, if this parameter is NULL, then handles
201 for all the children of Controller are created by this driver.
202 If this parameter is not NULL and the first Device Path Node is
203 not the End of Device Path Node, then only the handle for the
204 child device specified by the first Device Path Node of
205 RemainingDevicePath is created by this driver.
206 If the first Device Path Node of RemainingDevicePath is
207 the End of Device Path Node, no child handle is created by this
210 @retval EFI_SUCCESS The device was started.
211 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
212 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
213 @retval Others The driver failded to start the device.
218 HttpBootIp4DxeDriverBindingStart (
219 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
220 IN EFI_HANDLE ControllerHandle
,
221 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
225 HTTP_BOOT_PRIVATE_DATA
*Private
;
227 EFI_DEVICE_PATH_PROTOCOL
*DevicePath
;
230 Status
= gBS
->OpenProtocol (
234 This
->DriverBindingHandle
,
236 EFI_OPEN_PROTOCOL_GET_PROTOCOL
238 if (!EFI_ERROR (Status
)) {
239 return EFI_ALREADY_STARTED
;
243 // Initialize the private data structure.
245 Private
= AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA
));
246 if (Private
== NULL
) {
247 return EFI_OUT_OF_RESOURCES
;
249 Private
->Signature
= HTTP_BOOT_PRIVATE_DATA_SIGNATURE
;
250 Private
->Controller
= ControllerHandle
;
251 Private
->Image
= This
->ImageHandle
;
252 Private
->UsingIpv6
= FALSE
;
253 InitializeListHead (&Private
->CacheList
);
256 // Create DHCP child instance.
258 Status
= NetLibCreateServiceChild (
260 This
->DriverBindingHandle
,
261 &gEfiDhcp4ServiceBindingProtocolGuid
,
264 if (EFI_ERROR (Status
)) {
268 Status
= gBS
->OpenProtocol (
270 &gEfiDhcp4ProtocolGuid
,
271 (VOID
**) &Private
->Dhcp4
,
272 This
->DriverBindingHandle
,
274 EFI_OPEN_PROTOCOL_BY_DRIVER
276 if (EFI_ERROR (Status
)) {
281 // Get the Ip4Config2 protocol, it's required to configure the default gateway address.
283 Status
= gBS
->OpenProtocol (
285 &gEfiIp4Config2ProtocolGuid
,
286 (VOID
**) &Private
->Ip4Config2
,
287 This
->DriverBindingHandle
,
289 EFI_OPEN_PROTOCOL_GET_PROTOCOL
291 if (EFI_ERROR (Status
)) {
296 // Get the NII interface if it exists, it's not required.
298 Status
= gBS
->OpenProtocol (
300 &gEfiNetworkInterfaceIdentifierProtocolGuid_31
,
301 (VOID
**) &Private
->Nii
,
302 This
->DriverBindingHandle
,
304 EFI_OPEN_PROTOCOL_GET_PROTOCOL
306 if (EFI_ERROR (Status
)) {
311 // Open Device Path Protocol to prepare for appending IP and URI node.
313 Status
= gBS
->OpenProtocol (
315 &gEfiDevicePathProtocolGuid
,
316 (VOID
**) &Private
->ParentDevicePath
,
317 This
->DriverBindingHandle
,
319 EFI_OPEN_PROTOCOL_GET_PROTOCOL
321 if (EFI_ERROR (Status
)) {
326 // Append IPv4 device path node.
328 Node
= AllocateZeroPool (sizeof (IPv4_DEVICE_PATH
));
330 Status
= EFI_OUT_OF_RESOURCES
;
333 Node
->Ipv4
.Header
.Type
= MESSAGING_DEVICE_PATH
;
334 Node
->Ipv4
.Header
.SubType
= MSG_IPv4_DP
;
335 SetDevicePathNodeLength (Node
, sizeof (IPv4_DEVICE_PATH
));
336 Node
->Ipv4
.StaticIpAddress
= FALSE
;
337 DevicePath
= AppendDevicePathNode (Private
->ParentDevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
339 if (DevicePath
== NULL
) {
340 Status
= EFI_OUT_OF_RESOURCES
;
345 // Append URI device path node.
347 Node
= AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL
));
349 Status
= EFI_OUT_OF_RESOURCES
;
352 Node
->DevPath
.Type
= MESSAGING_DEVICE_PATH
;
353 Node
->DevPath
.SubType
= MSG_URI_DP
;
354 SetDevicePathNodeLength (Node
, sizeof (EFI_DEVICE_PATH_PROTOCOL
));
355 Private
->DevicePath
= AppendDevicePathNode (DevicePath
, (EFI_DEVICE_PATH_PROTOCOL
*) Node
);
357 FreePool (DevicePath
);
358 if (Private
->DevicePath
== NULL
) {
359 Status
= EFI_OUT_OF_RESOURCES
;
364 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.
366 CopyMem (&Private
->LoadFile
, &gHttpBootDxeLoadFile
, sizeof (Private
->LoadFile
));
367 Status
= gBS
->InstallMultipleProtocolInterfaces (
368 &Private
->ChildHandle
,
369 &gEfiLoadFileProtocolGuid
,
371 &gEfiDevicePathProtocolGuid
,
375 if (EFI_ERROR (Status
)) {
380 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between
381 // NIC handle and the private data.
383 Status
= gBS
->InstallProtocolInterface (
386 EFI_NATIVE_INTERFACE
,
389 if (EFI_ERROR (Status
)) {
394 // Open the Caller Id child to setup a parent-child relationship between
395 // real NIC handle and the HTTP boot child handle.
397 Status
= gBS
->OpenProtocol (
401 This
->DriverBindingHandle
,
402 Private
->ChildHandle
,
403 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
405 if (EFI_ERROR (Status
)) {
413 HttpBootDestroyIp4Children (This
, Private
);
420 Stops a device controller or a bus controller.
422 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
423 As a result, much of the error checking on the parameters to Stop() has been moved
424 into this common boot service. It is legal to call Stop() from other locations,
425 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
426 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
427 same driver's Start() function.
428 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
429 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
430 Start() function, and the Start() function must have called OpenProtocol() on
431 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
433 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
434 @param[in] ControllerHandle A handle to the device being stopped. The handle must
435 support a bus specific I/O protocol for the driver
436 to use to stop the device.
437 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
438 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
439 if NumberOfChildren is 0.
441 @retval EFI_SUCCESS The device was stopped.
442 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
447 HttpBootIp4DxeDriverBindingStop (
448 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
449 IN EFI_HANDLE ControllerHandle
,
450 IN UINTN NumberOfChildren
,
451 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
455 EFI_LOAD_FILE_PROTOCOL
*LoadFile
;
456 HTTP_BOOT_PRIVATE_DATA
*Private
;
457 EFI_HANDLE NicHandle
;
461 // Try to get the Load File Protocol from the controller handle.
463 Status
= gBS
->OpenProtocol (
465 &gEfiLoadFileProtocolGuid
,
467 This
->DriverBindingHandle
,
469 EFI_OPEN_PROTOCOL_GET_PROTOCOL
471 if (EFI_ERROR (Status
)) {
473 // If failed, try to find the NIC handle for this controller.
475 NicHandle
= HttpBootGetNicByIp4Children (ControllerHandle
);
476 if (NicHandle
== NULL
) {
481 // Try to retrieve the private data by the Caller Id Guid.
483 Status
= gBS
->OpenProtocol (
487 This
->DriverBindingHandle
,
489 EFI_OPEN_PROTOCOL_GET_PROTOCOL
491 if (EFI_ERROR (Status
)) {
494 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id
);
496 Private
= HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile
);
497 NicHandle
= Private
->Controller
;
501 // Disable the HTTP boot function.
503 Status
= HttpBootStop (Private
);
504 if (Status
!= EFI_SUCCESS
&& Status
!= EFI_NOT_STARTED
) {
509 // Destory all child instance and uninstall protocol interface.
511 HttpBootDestroyIp4Children (This
, Private
);
514 // Release the cached data.
516 HttpBootFreeCacheList (Private
);
518 gBS
->UninstallProtocolInterface (
529 This is the declaration of an EFI image entry point. This entry point is
530 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
531 both device drivers and bus drivers.
533 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
534 @param[in] SystemTable A pointer to the EFI System Table.
536 @retval EFI_SUCCESS The operation completed successfully.
537 @retval Others An unexpected error occurred.
542 HttpBootDxeDriverEntryPoint (
543 IN EFI_HANDLE ImageHandle
,
544 IN EFI_SYSTEM_TABLE
*SystemTable
548 // Install UEFI Driver Model protocol(s).
550 return EfiLibInstallDriverBindingComponentName2 (
553 &gHttpBootIp4DxeDriverBinding
,
555 &gHttpBootDxeComponentName
,
556 &gHttpBootDxeComponentName2