]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpBootDxe/HttpBootDxe.c
MdeModulePkg/AtaAtapiPassThru: disable only BM-DMA at ExitBootServices()
[mirror_edk2.git] / NetworkPkg / HttpBootDxe / HttpBootDxe.c
CommitLineData
d933e70a
JW
1/** @file\r
2 Driver Binding functions implementation for UEFI HTTP boot.\r
3\r
ed247d86 4Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
d933e70a
JW
5This program and the accompanying materials are licensed and made available under \r
6the terms and conditions of the BSD License that accompanies this distribution. \r
7The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php. \r
9 \r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
12\r
13**/\r
14\r
15#include "HttpBootDxe.h"\r
16\r
17///\r
18/// Driver Binding Protocol instance\r
19///\r
20EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp4DxeDriverBinding = {\r
21 HttpBootIp4DxeDriverBindingSupported,\r
22 HttpBootIp4DxeDriverBindingStart,\r
23 HttpBootIp4DxeDriverBindingStop,\r
24 HTTP_BOOT_DXE_VERSION,\r
25 NULL,\r
26 NULL\r
27};\r
28\r
b659408b
ZL
29EFI_DRIVER_BINDING_PROTOCOL gHttpBootIp6DxeDriverBinding = {\r
30 HttpBootIp6DxeDriverBindingSupported,\r
31 HttpBootIp6DxeDriverBindingStart,\r
32 HttpBootIp6DxeDriverBindingStop,\r
33 HTTP_BOOT_DXE_VERSION,\r
34 NULL,\r
35 NULL\r
36};\r
37\r
ed247d86
JW
38\r
39\r
40/**\r
41 Check whether UNDI protocol supports IPv6.\r
42\r
43 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.\r
44 @param[out] Ipv6Support TRUE if UNDI supports IPv6.\r
45\r
46 @retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully.\r
47 @retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available.\r
48\r
49**/\r
50EFI_STATUS\r
51HttpBootCheckIpv6Support (\r
52 IN HTTP_BOOT_PRIVATE_DATA *Private,\r
53 OUT BOOLEAN *Ipv6Support\r
54 )\r
55{\r
56 EFI_HANDLE Handle;\r
57 EFI_ADAPTER_INFORMATION_PROTOCOL *Aip;\r
58 EFI_STATUS Status;\r
59 EFI_GUID *InfoTypesBuffer;\r
60 UINTN InfoTypeBufferCount;\r
61 UINTN TypeIndex;\r
62 BOOLEAN Supported;\r
63 VOID *InfoBlock;\r
64 UINTN InfoBlockSize;\r
65\r
66 ASSERT (Private != NULL && Ipv6Support != NULL);\r
67\r
68 //\r
69 // Check whether the UNDI supports IPv6 by NII protocol.\r
70 //\r
71 if (Private->Nii != NULL) {\r
72 *Ipv6Support = Private->Nii->Ipv6Supported;\r
73 return EFI_SUCCESS;\r
74 }\r
75\r
76 //\r
77 // Get the NIC handle by SNP protocol.\r
78 // \r
79 Handle = NetLibGetSnpHandle (Private->Controller, NULL);\r
80 if (Handle == NULL) {\r
81 return EFI_NOT_FOUND;\r
82 }\r
83\r
84 Aip = NULL;\r
85 Status = gBS->HandleProtocol (\r
86 Handle,\r
87 &gEfiAdapterInformationProtocolGuid,\r
88 (VOID *) &Aip\r
89 );\r
90 if (EFI_ERROR (Status) || Aip == NULL) {\r
91 return EFI_NOT_FOUND;\r
92 }\r
93\r
94 InfoTypesBuffer = NULL;\r
95 InfoTypeBufferCount = 0;\r
96 Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount);\r
97 if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) {\r
98 FreePool (InfoTypesBuffer);\r
99 return EFI_NOT_FOUND;\r
100 }\r
101\r
102 Supported = FALSE;\r
103 for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) {\r
104 if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {\r
105 Supported = TRUE;\r
106 break;\r
107 }\r
108 }\r
109\r
110 FreePool (InfoTypesBuffer);\r
111 if (!Supported) {\r
112 return EFI_NOT_FOUND;\r
113 }\r
114\r
115 //\r
116 // We now have adapter information block.\r
117 //\r
118 InfoBlock = NULL;\r
119 InfoBlockSize = 0;\r
120 Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize);\r
121 if (EFI_ERROR (Status) || InfoBlock == NULL) {\r
122 FreePool (InfoBlock);\r
123 return EFI_NOT_FOUND;\r
124 } \r
125\r
126 *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support;\r
127 FreePool (InfoBlock);\r
128 \r
129 return EFI_SUCCESS;\r
130}\r
131\r
d933e70a
JW
132/**\r
133 Destroy the HTTP child based on IPv4 stack.\r
134\r
135 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.\r
136 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.\r
137\r
138**/\r
139VOID\r
140HttpBootDestroyIp4Children (\r
141 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
142 IN HTTP_BOOT_PRIVATE_DATA *Private\r
143 )\r
144{\r
145 ASSERT (This != NULL);\r
146 ASSERT (Private != NULL);\r
d933e70a
JW
147\r
148 if (Private->Dhcp4Child != NULL) {\r
149 gBS->CloseProtocol (\r
b659408b
ZL
150 Private->Dhcp4Child,\r
151 &gEfiDhcp4ProtocolGuid,\r
152 This->DriverBindingHandle,\r
153 Private->Controller\r
154 );\r
d933e70a
JW
155\r
156 NetLibDestroyServiceChild (\r
157 Private->Controller,\r
158 This->DriverBindingHandle,\r
159 &gEfiDhcp4ServiceBindingProtocolGuid,\r
160 Private->Dhcp4Child\r
161 );\r
162 }\r
163\r
ed247d86 164 if (Private->Ip6Nic == NULL && Private->HttpCreated) {\r
d933e70a
JW
165 HttpIoDestroyIo (&Private->HttpIo);\r
166 Private->HttpCreated = FALSE;\r
167 }\r
168\r
b659408b
ZL
169 if (Private->Ip4Nic != NULL) {\r
170 \r
171 gBS->CloseProtocol (\r
172 Private->Controller,\r
173 &gEfiCallerIdGuid,\r
174 This->DriverBindingHandle,\r
175 Private->Ip4Nic->Controller\r
176 );\r
177 \r
178 gBS->UninstallMultipleProtocolInterfaces (\r
179 Private->Ip4Nic->Controller,\r
180 &gEfiLoadFileProtocolGuid,\r
181 &Private->Ip4Nic->LoadFile,\r
182 &gEfiDevicePathProtocolGuid,\r
183 Private->Ip4Nic->DevicePath,\r
184 NULL\r
185 );\r
186 FreePool (Private->Ip4Nic);\r
187 Private->Ip4Nic = NULL;\r
188 }\r
189\r
190}\r
191\r
192/**\r
193 Destroy the HTTP child based on IPv6 stack.\r
194\r
195 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.\r
196 @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA.\r
197\r
198**/\r
199VOID\r
200HttpBootDestroyIp6Children (\r
201 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
202 IN HTTP_BOOT_PRIVATE_DATA *Private\r
203 )\r
204{\r
205 ASSERT (This != NULL);\r
206 ASSERT (Private != NULL);\r
b659408b
ZL
207 \r
208 if (Private->Ip6Child != NULL) {\r
209 gBS->CloseProtocol (\r
210 Private->Ip6Child,\r
211 &gEfiIp6ProtocolGuid,\r
212 This->DriverBindingHandle,\r
213 Private->Controller\r
214 );\r
215\r
216 NetLibDestroyServiceChild (\r
217 Private->Controller,\r
218 This->DriverBindingHandle,\r
219 &gEfiIp6ServiceBindingProtocolGuid,\r
220 Private->Ip6Child\r
221 );\r
222 }\r
223\r
224 if (Private->Dhcp6Child != NULL) {\r
225 gBS->CloseProtocol (\r
226 Private->Dhcp6Child,\r
227 &gEfiDhcp6ProtocolGuid,\r
228 This->DriverBindingHandle,\r
229 Private->Controller\r
230 );\r
d933e70a 231\r
b659408b
ZL
232 NetLibDestroyServiceChild (\r
233 Private->Controller,\r
234 This->DriverBindingHandle,\r
235 &gEfiDhcp6ServiceBindingProtocolGuid,\r
236 Private->Dhcp6Child\r
237 );\r
238 }\r
d933e70a 239\r
ed247d86 240 if (Private->Ip4Nic == NULL && Private->HttpCreated) {\r
b659408b
ZL
241 HttpIoDestroyIo(&Private->HttpIo);\r
242 Private->HttpCreated = FALSE;\r
243 }\r
244 \r
245 if (Private->Ip6Nic != NULL) {\r
246 \r
247 gBS->CloseProtocol (\r
248 Private->Controller,\r
249 &gEfiCallerIdGuid,\r
250 This->DriverBindingHandle,\r
251 Private->Ip6Nic->Controller\r
252 );\r
253 \r
254 gBS->UninstallMultipleProtocolInterfaces (\r
255 Private->Ip6Nic->Controller,\r
256 &gEfiLoadFileProtocolGuid,\r
257 &Private->Ip6Nic->LoadFile,\r
258 &gEfiDevicePathProtocolGuid,\r
259 Private->Ip6Nic->DevicePath,\r
260 NULL\r
261 );\r
262 FreePool (Private->Ip6Nic);\r
263 Private->Ip6Nic = NULL;\r
d933e70a
JW
264 }\r
265}\r
266\r
267/**\r
268 Tests to see if this driver supports a given controller. If a child device is provided, \r
269 it further tests to see if this driver supports creating a handle for the specified child device.\r
270\r
271 This function checks to see if the driver specified by This supports the device specified by \r
272 ControllerHandle. Drivers will typically use the device path attached to \r
273 ControllerHandle and/or the services from the bus I/O abstraction attached to \r
274 ControllerHandle to determine if the driver supports ControllerHandle. This function \r
275 may be called many times during platform initialization. In order to reduce boot times, the tests \r
276 performed by this function must be very small, and take as little time as possible to execute. This \r
277 function must not change the state of any hardware devices, and this function must be aware that the \r
278 device specified by ControllerHandle may already be managed by the same driver or a \r
279 different driver. This function must match its calls to AllocatePages() with FreePages(), \r
280 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
281 Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
282 already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
283 to guarantee the state of ControllerHandle is not modified by this function.\r
284\r
285 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
286 @param[in] ControllerHandle The handle of the controller to test. This handle \r
287 must support a protocol interface that supplies \r
288 an I/O abstraction to the driver.\r
289 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
290 parameter is ignored by device drivers, and is optional for bus \r
291 drivers. For bus drivers, if this parameter is not NULL, then \r
292 the bus driver must determine if the bus controller specified \r
293 by ControllerHandle and the child controller specified \r
294 by RemainingDevicePath are both supported by this \r
295 bus driver.\r
296\r
297 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
298 RemainingDevicePath is supported by the driver specified by This.\r
299 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
300 RemainingDevicePath is already being managed by the driver\r
301 specified by This.\r
302 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
303 RemainingDevicePath is already being managed by a different\r
304 driver or an application that requires exclusive access.\r
305 Currently not implemented.\r
306 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
307 RemainingDevicePath is not supported by the driver specified by This.\r
308**/\r
309EFI_STATUS\r
310EFIAPI\r
311HttpBootIp4DxeDriverBindingSupported (\r
312 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
313 IN EFI_HANDLE ControllerHandle,\r
314 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
315 )\r
316{\r
317 EFI_STATUS Status;\r
318 \r
319 //\r
320 // Try to open the DHCP4, HTTP4 and Device Path protocol.\r
321 //\r
322 Status = gBS->OpenProtocol (\r
b659408b
ZL
323 ControllerHandle,\r
324 &gEfiDhcp4ServiceBindingProtocolGuid,\r
325 NULL,\r
326 This->DriverBindingHandle,\r
327 ControllerHandle,\r
328 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
329 );\r
d933e70a
JW
330 if (EFI_ERROR (Status)) {\r
331 return Status;\r
332 }\r
333\r
334 Status = gBS->OpenProtocol (\r
b659408b
ZL
335 ControllerHandle,\r
336 &gEfiHttpServiceBindingProtocolGuid,\r
337 NULL,\r
338 This->DriverBindingHandle,\r
339 ControllerHandle,\r
340 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
341 );\r
d933e70a
JW
342 if (EFI_ERROR (Status)) {\r
343 return Status;\r
344 }\r
345\r
346 Status = gBS->OpenProtocol (\r
b659408b
ZL
347 ControllerHandle,\r
348 &gEfiDevicePathProtocolGuid,\r
349 NULL,\r
350 This->DriverBindingHandle,\r
351 ControllerHandle,\r
352 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
353 );\r
d933e70a
JW
354\r
355 return Status;\r
356}\r
357\r
358\r
359/**\r
360 Starts a device controller or a bus controller.\r
361\r
362 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
363 As a result, much of the error checking on the parameters to Start() has been moved into this \r
364 common boot service. It is legal to call Start() from other locations, \r
365 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
366 1. ControllerHandle must be a valid EFI_HANDLE.\r
367 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
368 EFI_DEVICE_PATH_PROTOCOL.\r
369 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
370 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
371\r
372 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
373 @param[in] ControllerHandle The handle of the controller to start. This handle \r
374 must support a protocol interface that supplies \r
375 an I/O abstraction to the driver.\r
376 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
377 parameter is ignored by device drivers, and is optional for bus \r
378 drivers. For a bus driver, if this parameter is NULL, then handles \r
379 for all the children of Controller are created by this driver. \r
380 If this parameter is not NULL and the first Device Path Node is \r
381 not the End of Device Path Node, then only the handle for the \r
382 child device specified by the first Device Path Node of \r
383 RemainingDevicePath is created by this driver.\r
384 If the first Device Path Node of RemainingDevicePath is \r
385 the End of Device Path Node, no child handle is created by this\r
386 driver.\r
387\r
388 @retval EFI_SUCCESS The device was started.\r
389 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
390 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
391 @retval Others The driver failded to start the device.\r
392\r
393**/\r
394EFI_STATUS\r
395EFIAPI\r
396HttpBootIp4DxeDriverBindingStart (\r
397 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
398 IN EFI_HANDLE ControllerHandle,\r
399 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
400 )\r
401{\r
402 EFI_STATUS Status;\r
403 HTTP_BOOT_PRIVATE_DATA *Private;\r
404 EFI_DEV_PATH *Node;\r
405 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
406 UINT32 *Id;\r
ed247d86
JW
407 BOOLEAN FirstStart;\r
408\r
409 FirstStart = FALSE;\r
d933e70a
JW
410\r
411 Status = gBS->OpenProtocol (\r
412 ControllerHandle,\r
413 &gEfiCallerIdGuid,\r
414 (VOID **) &Id,\r
415 This->DriverBindingHandle,\r
416 ControllerHandle,\r
417 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
418 );\r
b659408b 419\r
d933e70a 420 if (!EFI_ERROR (Status)) {\r
75372581 421 Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);\r
b659408b 422 } else {\r
ed247d86
JW
423 FirstStart = TRUE;\r
424 \r
b659408b
ZL
425 //\r
426 // Initialize the private data structure.\r
427 //\r
428 Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));\r
429 if (Private == NULL) {\r
430 return EFI_OUT_OF_RESOURCES;\r
431 }\r
432 Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;\r
433 Private->Controller = ControllerHandle;\r
b659408b
ZL
434 InitializeListHead (&Private->CacheList);\r
435 //\r
436 // Get the NII interface if it exists, it's not required.\r
437 //\r
438 Status = gBS->OpenProtocol (\r
439 ControllerHandle,\r
440 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
441 (VOID **) &Private->Nii,\r
442 This->DriverBindingHandle,\r
443 ControllerHandle,\r
444 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
445 );\r
446 if (EFI_ERROR (Status)) {\r
447 Private->Nii = NULL;\r
448 }\r
d933e70a 449\r
b659408b
ZL
450 //\r
451 // Open Device Path Protocol to prepare for appending IP and URI node.\r
452 //\r
453 Status = gBS->OpenProtocol (\r
454 ControllerHandle,\r
455 &gEfiDevicePathProtocolGuid,\r
456 (VOID **) &Private->ParentDevicePath,\r
457 This->DriverBindingHandle,\r
458 ControllerHandle,\r
459 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
460 );\r
461 if (EFI_ERROR (Status)) {\r
462 goto ON_ERROR;\r
463 }\r
464\r
fa848a40
FS
465 //\r
466 // Initialize the HII configuration form.\r
467 //\r
468 Status = HttpBootConfigFormInit (Private);\r
469 if (EFI_ERROR (Status)) {\r
470 goto ON_ERROR;\r
471 }\r
472\r
b659408b
ZL
473 //\r
474 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between\r
475 // NIC handle and the private data.\r
476 //\r
477 Status = gBS->InstallProtocolInterface (\r
478 &ControllerHandle,\r
479 &gEfiCallerIdGuid,\r
480 EFI_NATIVE_INTERFACE,\r
481 &Private->Id\r
482 );\r
483 if (EFI_ERROR (Status)) {\r
484 goto ON_ERROR;\r
485 }\r
486 \r
487 }\r
488 \r
489 if (Private->Ip4Nic != NULL) {\r
490 //\r
491 // Already created before\r
492 //\r
493 return EFI_SUCCESS;\r
494 }\r
495 \r
496 Private->Ip4Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));\r
497 if (Private->Ip4Nic == NULL) {\r
ed247d86
JW
498 Status = EFI_OUT_OF_RESOURCES;\r
499 goto ON_ERROR;\r
d933e70a 500 }\r
75372581
FS
501 Private->Ip4Nic->Private = Private;\r
502 Private->Ip4Nic->ImageHandle = This->DriverBindingHandle;\r
503 Private->Ip4Nic->Signature = HTTP_BOOT_VIRTUAL_NIC_SIGNATURE;\r
b659408b 504 \r
d933e70a 505 //\r
b659408b 506 // Create DHCP4 child instance.\r
d933e70a
JW
507 //\r
508 Status = NetLibCreateServiceChild (\r
509 ControllerHandle,\r
510 This->DriverBindingHandle,\r
511 &gEfiDhcp4ServiceBindingProtocolGuid,\r
512 &Private->Dhcp4Child\r
513 );\r
514 if (EFI_ERROR (Status)) {\r
515 goto ON_ERROR;\r
516 }\r
b659408b 517 \r
d933e70a
JW
518 Status = gBS->OpenProtocol (\r
519 Private->Dhcp4Child,\r
520 &gEfiDhcp4ProtocolGuid,\r
521 (VOID **) &Private->Dhcp4,\r
522 This->DriverBindingHandle,\r
523 ControllerHandle,\r
524 EFI_OPEN_PROTOCOL_BY_DRIVER\r
525 );\r
526 if (EFI_ERROR (Status)) {\r
527 goto ON_ERROR;\r
528 }\r
b659408b 529 \r
d933e70a
JW
530 //\r
531 // Get the Ip4Config2 protocol, it's required to configure the default gateway address.\r
532 //\r
533 Status = gBS->OpenProtocol (\r
534 ControllerHandle,\r
535 &gEfiIp4Config2ProtocolGuid,\r
536 (VOID **) &Private->Ip4Config2,\r
537 This->DriverBindingHandle,\r
538 ControllerHandle,\r
539 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
540 );\r
541 if (EFI_ERROR (Status)) {\r
542 goto ON_ERROR;\r
543 }\r
b659408b 544 \r
d933e70a
JW
545 //\r
546 // Append IPv4 device path node.\r
547 //\r
548 Node = AllocateZeroPool (sizeof (IPv4_DEVICE_PATH));\r
549 if (Node == NULL) {\r
550 Status = EFI_OUT_OF_RESOURCES;\r
551 goto ON_ERROR;\r
552 }\r
553 Node->Ipv4.Header.Type = MESSAGING_DEVICE_PATH;\r
554 Node->Ipv4.Header.SubType = MSG_IPv4_DP;\r
555 SetDevicePathNodeLength (Node, sizeof (IPv4_DEVICE_PATH));\r
556 Node->Ipv4.StaticIpAddress = FALSE;\r
557 DevicePath = AppendDevicePathNode (Private->ParentDevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
558 FreePool (Node);\r
559 if (DevicePath == NULL) {\r
560 Status = EFI_OUT_OF_RESOURCES;\r
561 goto ON_ERROR;\r
562 }\r
b659408b 563 \r
d933e70a
JW
564 //\r
565 // Append URI device path node.\r
566 //\r
567 Node = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
568 if (Node == NULL) {\r
569 Status = EFI_OUT_OF_RESOURCES;\r
570 goto ON_ERROR;\r
571 }\r
572 Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
573 Node->DevPath.SubType = MSG_URI_DP;\r
574 SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
b659408b 575 Private->Ip4Nic->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
d933e70a
JW
576 FreePool (Node);\r
577 FreePool (DevicePath);\r
b659408b 578 if (Private->Ip4Nic->DevicePath == NULL) {\r
d933e70a
JW
579 Status = EFI_OUT_OF_RESOURCES;\r
580 goto ON_ERROR;\r
581 }\r
b659408b 582 \r
d933e70a
JW
583 //\r
584 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.\r
585 //\r
b659408b 586 CopyMem (&Private->Ip4Nic->LoadFile, &gHttpBootDxeLoadFile, sizeof (EFI_LOAD_FILE_PROTOCOL));\r
d933e70a 587 Status = gBS->InstallMultipleProtocolInterfaces (\r
b659408b 588 &Private->Ip4Nic->Controller,\r
d933e70a 589 &gEfiLoadFileProtocolGuid,\r
b659408b 590 &Private->Ip4Nic->LoadFile,\r
d933e70a 591 &gEfiDevicePathProtocolGuid,\r
b659408b 592 Private->Ip4Nic->DevicePath,\r
d933e70a
JW
593 NULL\r
594 );\r
595 if (EFI_ERROR (Status)) {\r
596 goto ON_ERROR;\r
597 }\r
b659408b 598 \r
d933e70a
JW
599 //\r
600 // Open the Caller Id child to setup a parent-child relationship between\r
b659408b 601 // real NIC handle and the HTTP boot Ipv4 NIC handle.\r
d933e70a
JW
602 //\r
603 Status = gBS->OpenProtocol (\r
604 ControllerHandle,\r
605 &gEfiCallerIdGuid,\r
606 (VOID **) &Id,\r
607 This->DriverBindingHandle,\r
b659408b 608 Private->Ip4Nic->Controller,\r
d933e70a
JW
609 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
610 );\r
611 if (EFI_ERROR (Status)) {\r
612 goto ON_ERROR;\r
613 }\r
b659408b 614 \r
d933e70a 615 return EFI_SUCCESS;\r
b659408b 616 \r
d933e70a 617ON_ERROR:\r
ed247d86
JW
618 if (FirstStart) {\r
619 gBS->UninstallProtocolInterface (\r
620 ControllerHandle,\r
621 &gEfiCallerIdGuid,\r
622 &Private->Id\r
623 );\r
624 }\r
625 \r
d933e70a 626 HttpBootDestroyIp4Children (This, Private);\r
fa848a40 627 HttpBootConfigFormUnload (Private);\r
ed247d86
JW
628\r
629 if (FirstStart && Private != NULL) {\r
630 FreePool (Private);\r
631 }\r
d933e70a
JW
632\r
633 return Status;\r
634}\r
635\r
b659408b 636\r
d933e70a
JW
637/**\r
638 Stops a device controller or a bus controller.\r
639 \r
640 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
641 As a result, much of the error checking on the parameters to Stop() has been moved \r
642 into this common boot service. It is legal to call Stop() from other locations, \r
643 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
644 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
645 same driver's Start() function.\r
646 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
647 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
648 Start() function, and the Start() function must have called OpenProtocol() on\r
649 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
650 \r
651 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
652 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
653 support a bus specific I/O protocol for the driver \r
654 to use to stop the device.\r
655 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
656 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
657 if NumberOfChildren is 0.\r
658\r
659 @retval EFI_SUCCESS The device was stopped.\r
660 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
661\r
662**/\r
663EFI_STATUS\r
664EFIAPI\r
665HttpBootIp4DxeDriverBindingStop (\r
666 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
667 IN EFI_HANDLE ControllerHandle,\r
668 IN UINTN NumberOfChildren,\r
669 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
670 )\r
671{\r
672 EFI_STATUS Status;\r
673 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
674 HTTP_BOOT_PRIVATE_DATA *Private;\r
675 EFI_HANDLE NicHandle;\r
676 UINT32 *Id;\r
677\r
678 //\r
679 // Try to get the Load File Protocol from the controller handle.\r
680 //\r
681 Status = gBS->OpenProtocol (\r
682 ControllerHandle,\r
683 &gEfiLoadFileProtocolGuid,\r
684 (VOID **) &LoadFile,\r
685 This->DriverBindingHandle,\r
686 ControllerHandle,\r
687 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
688 );\r
689 if (EFI_ERROR (Status)) {\r
690 //\r
691 // If failed, try to find the NIC handle for this controller.\r
692 //\r
693 NicHandle = HttpBootGetNicByIp4Children (ControllerHandle);\r
694 if (NicHandle == NULL) {\r
695 return EFI_SUCCESS;\r
696 }\r
697\r
698 //\r
699 // Try to retrieve the private data by the Caller Id Guid.\r
700 //\r
701 Status = gBS->OpenProtocol (\r
702 NicHandle,\r
703 &gEfiCallerIdGuid,\r
704 (VOID **) &Id,\r
705 This->DriverBindingHandle,\r
706 ControllerHandle,\r
707 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
708 );\r
709 if (EFI_ERROR (Status)) {\r
710 return Status;\r
711 }\r
712 Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id);\r
713 } else {\r
714 Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile);\r
715 NicHandle = Private->Controller;\r
716 }\r
717\r
718 //\r
719 // Disable the HTTP boot function.\r
720 //\r
721 Status = HttpBootStop (Private);\r
722 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {\r
723 return Status;\r
724 }\r
725\r
726 //\r
727 // Destory all child instance and uninstall protocol interface.\r
728 //\r
729 HttpBootDestroyIp4Children (This, Private);\r
b659408b
ZL
730 \r
731 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
732 //\r
733 // Release the cached data.\r
734 //\r
735 HttpBootFreeCacheList (Private);\r
fa848a40
FS
736\r
737 //\r
738 // Unload the config form.\r
739 //\r
740 HttpBootConfigFormUnload (Private);\r
b659408b
ZL
741 \r
742 gBS->UninstallProtocolInterface (\r
743 NicHandle,\r
744 &gEfiCallerIdGuid,\r
745 &Private->Id\r
746 );\r
747 FreePool (Private);\r
d933e70a 748\r
b659408b 749 }\r
d933e70a
JW
750\r
751 return EFI_SUCCESS;\r
752}\r
753\r
754/**\r
b659408b
ZL
755 Tests to see if this driver supports a given controller. If a child device is provided, \r
756 it further tests to see if this driver supports creating a handle for the specified child device.\r
d933e70a 757\r
b659408b
ZL
758 This function checks to see if the driver specified by This supports the device specified by \r
759 ControllerHandle. Drivers will typically use the device path attached to \r
760 ControllerHandle and/or the services from the bus I/O abstraction attached to \r
761 ControllerHandle to determine if the driver supports ControllerHandle. This function \r
762 may be called many times during platform initialization. In order to reduce boot times, the tests \r
763 performed by this function must be very small, and take as little time as possible to execute. This \r
764 function must not change the state of any hardware devices, and this function must be aware that the \r
765 device specified by ControllerHandle may already be managed by the same driver or a \r
766 different driver. This function must match its calls to AllocatePages() with FreePages(), \r
767 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol(). \r
768 Because ControllerHandle may have been previously started by the same driver, if a protocol is \r
769 already in the opened state, then it must not be closed with CloseProtocol(). This is required \r
770 to guarantee the state of ControllerHandle is not modified by this function.\r
d933e70a 771\r
b659408b
ZL
772 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
773 @param[in] ControllerHandle The handle of the controller to test. This handle \r
774 must support a protocol interface that supplies \r
775 an I/O abstraction to the driver.\r
776 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
777 parameter is ignored by device drivers, and is optional for bus \r
778 drivers. For bus drivers, if this parameter is not NULL, then \r
779 the bus driver must determine if the bus controller specified \r
780 by ControllerHandle and the child controller specified \r
781 by RemainingDevicePath are both supported by this \r
782 bus driver.\r
d933e70a 783\r
b659408b
ZL
784 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
785 RemainingDevicePath is supported by the driver specified by This.\r
786 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
787 RemainingDevicePath is already being managed by the driver\r
788 specified by This.\r
789 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
790 RemainingDevicePath is already being managed by a different\r
791 driver or an application that requires exclusive access.\r
792 Currently not implemented.\r
793 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
794 RemainingDevicePath is not supported by the driver specified by This.\r
d933e70a
JW
795**/\r
796EFI_STATUS\r
797EFIAPI\r
b659408b
ZL
798HttpBootIp6DxeDriverBindingSupported (\r
799 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
800 IN EFI_HANDLE ControllerHandle,\r
801 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
d933e70a
JW
802 )\r
803{\r
b659408b
ZL
804 EFI_STATUS Status;\r
805 \r
d933e70a 806 //\r
b659408b 807 // Try to open the DHCP6, HTTP and Device Path protocol.\r
d933e70a 808 //\r
b659408b
ZL
809 Status = gBS->OpenProtocol (\r
810 ControllerHandle,\r
811 &gEfiDhcp6ServiceBindingProtocolGuid,\r
812 NULL,\r
813 This->DriverBindingHandle,\r
814 ControllerHandle,\r
815 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
816 );\r
817 if (EFI_ERROR (Status)) {\r
818 return Status;\r
819 }\r
820\r
821 Status = gBS->OpenProtocol (\r
822 ControllerHandle,\r
823 &gEfiHttpServiceBindingProtocolGuid,\r
824 NULL,\r
825 This->DriverBindingHandle,\r
826 ControllerHandle,\r
827 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
828 );\r
829 if (EFI_ERROR (Status)) {\r
830 return Status;\r
831 }\r
832\r
833 Status = gBS->OpenProtocol (\r
834 ControllerHandle,\r
835 &gEfiDevicePathProtocolGuid,\r
836 NULL,\r
837 This->DriverBindingHandle,\r
838 ControllerHandle,\r
839 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
840 );\r
841\r
842 return Status;\r
843\r
844}\r
845\r
846/**\r
847 Starts a device controller or a bus controller.\r
848\r
849 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
850 As a result, much of the error checking on the parameters to Start() has been moved into this \r
851 common boot service. It is legal to call Start() from other locations, \r
852 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
853 1. ControllerHandle must be a valid EFI_HANDLE.\r
854 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
855 EFI_DEVICE_PATH_PROTOCOL.\r
856 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
857 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS. \r
858\r
859 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
860 @param[in] ControllerHandle The handle of the controller to start. This handle \r
861 must support a protocol interface that supplies \r
862 an I/O abstraction to the driver.\r
863 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This \r
864 parameter is ignored by device drivers, and is optional for bus \r
865 drivers. For a bus driver, if this parameter is NULL, then handles \r
866 for all the children of Controller are created by this driver. \r
867 If this parameter is not NULL and the first Device Path Node is \r
868 not the End of Device Path Node, then only the handle for the \r
869 child device specified by the first Device Path Node of \r
870 RemainingDevicePath is created by this driver.\r
871 If the first Device Path Node of RemainingDevicePath is \r
872 the End of Device Path Node, no child handle is created by this\r
873 driver.\r
874\r
875 @retval EFI_SUCCESS The device was started.\r
876 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
877 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
878 @retval Others The driver failded to start the device.\r
879\r
880**/\r
881EFI_STATUS\r
882EFIAPI\r
883HttpBootIp6DxeDriverBindingStart (\r
884 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
885 IN EFI_HANDLE ControllerHandle,\r
886 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
887 )\r
888{\r
889 EFI_STATUS Status;\r
890 HTTP_BOOT_PRIVATE_DATA *Private;\r
891 EFI_DEV_PATH *Node;\r
892 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
893 UINT32 *Id;\r
ed247d86
JW
894 BOOLEAN Ipv6Available;\r
895 BOOLEAN FirstStart;\r
896\r
897 FirstStart = FALSE;\r
b659408b
ZL
898 \r
899 Status = gBS->OpenProtocol (\r
900 ControllerHandle,\r
901 &gEfiCallerIdGuid,\r
902 (VOID **) &Id,\r
903 This->DriverBindingHandle,\r
904 ControllerHandle,\r
905 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
906 );\r
907 \r
908 if (!EFI_ERROR (Status)) {\r
75372581 909 Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);\r
b659408b 910 } else {\r
ed247d86
JW
911 FirstStart = TRUE;\r
912 \r
b659408b
ZL
913 //\r
914 // Initialize the private data structure.\r
915 //\r
916 Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));\r
917 if (Private == NULL) {\r
918 return EFI_OUT_OF_RESOURCES;\r
919 }\r
920 Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;\r
921 Private->Controller = ControllerHandle;\r
b659408b
ZL
922 InitializeListHead (&Private->CacheList);\r
923 //\r
924 // Get the NII interface if it exists, it's not required.\r
925 //\r
926 Status = gBS->OpenProtocol (\r
927 ControllerHandle,\r
928 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
929 (VOID **) &Private->Nii,\r
930 This->DriverBindingHandle,\r
931 ControllerHandle,\r
932 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
933 );\r
934 if (EFI_ERROR (Status)) {\r
935 Private->Nii = NULL;\r
936 }\r
937\r
938 //\r
939 // Open Device Path Protocol to prepare for appending IP and URI node.\r
940 //\r
941 Status = gBS->OpenProtocol (\r
942 ControllerHandle,\r
943 &gEfiDevicePathProtocolGuid,\r
944 (VOID **) &Private->ParentDevicePath,\r
945 This->DriverBindingHandle,\r
946 ControllerHandle,\r
947 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
948 );\r
949 if (EFI_ERROR (Status)) {\r
950 goto ON_ERROR;\r
951 }\r
952\r
fa848a40
FS
953 //\r
954 // Initialize the HII configuration form.\r
955 //\r
956 Status = HttpBootConfigFormInit (Private);\r
957 if (EFI_ERROR (Status)) {\r
958 goto ON_ERROR;\r
959 }\r
960\r
b659408b
ZL
961 //\r
962 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between\r
963 // NIC handle and the private data.\r
964 //\r
965 Status = gBS->InstallProtocolInterface (\r
966 &ControllerHandle,\r
967 &gEfiCallerIdGuid,\r
968 EFI_NATIVE_INTERFACE,\r
969 &Private->Id\r
970 );\r
971 if (EFI_ERROR (Status)) {\r
972 goto ON_ERROR;\r
973 }\r
974 \r
975 }\r
ed247d86
JW
976\r
977 //\r
978 // Set IPv6 available flag.\r
979 // \r
980 Status = HttpBootCheckIpv6Support (Private, &Ipv6Available);\r
981 if (EFI_ERROR (Status)) {\r
982 //\r
983 // Fail to get the data whether UNDI supports IPv6. \r
984 // Set default value to TRUE.\r
985 //\r
986 Ipv6Available = TRUE;\r
987 }\r
988\r
989 if (!Ipv6Available) {\r
990 Status = EFI_UNSUPPORTED;\r
991 goto ON_ERROR;\r
992 }\r
b659408b
ZL
993 \r
994 if (Private->Ip6Nic != NULL) {\r
995 //\r
996 // Already created before\r
997 //\r
998 return EFI_SUCCESS;\r
999 }\r
1000 \r
1001 Private->Ip6Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));\r
1002 if (Private->Ip6Nic == NULL) {\r
ed247d86
JW
1003 Status = EFI_OUT_OF_RESOURCES;\r
1004 goto ON_ERROR;\r
b659408b 1005 }\r
75372581
FS
1006 Private->Ip6Nic->Private = Private;\r
1007 Private->Ip6Nic->ImageHandle = This->DriverBindingHandle;\r
1008 Private->Ip6Nic->Signature = HTTP_BOOT_VIRTUAL_NIC_SIGNATURE;\r
1009 \r
b659408b
ZL
1010 //\r
1011 // Create Dhcp6 child and open Dhcp6 protocol\r
1012 Status = NetLibCreateServiceChild (\r
1013 ControllerHandle,\r
1014 This->DriverBindingHandle,\r
1015 &gEfiDhcp6ServiceBindingProtocolGuid,\r
1016 &Private->Dhcp6Child\r
1017 );\r
1018 if (EFI_ERROR (Status)) {\r
1019 goto ON_ERROR;\r
1020 }\r
1021\r
1022 Status = gBS->OpenProtocol (\r
1023 Private->Dhcp6Child,\r
1024 &gEfiDhcp6ProtocolGuid,\r
1025 (VOID **) &Private->Dhcp6,\r
1026 This->DriverBindingHandle,\r
1027 ControllerHandle,\r
1028 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1029 );\r
1030 if (EFI_ERROR (Status)) {\r
1031 goto ON_ERROR;\r
1032 }\r
1033\r
1034 //\r
1035 // Create Ip6 child and open Ip6 protocol for background ICMP packets.\r
1036 //\r
1037 Status = NetLibCreateServiceChild (\r
1038 ControllerHandle,\r
1039 This->DriverBindingHandle,\r
1040 &gEfiIp6ServiceBindingProtocolGuid,\r
1041 &Private->Ip6Child\r
1042 );\r
1043 if (EFI_ERROR (Status)) {\r
1044 goto ON_ERROR;\r
1045 }\r
1046\r
1047 Status = gBS->OpenProtocol (\r
1048 Private->Ip6Child,\r
1049 &gEfiIp6ProtocolGuid,\r
1050 (VOID **) &Private->Ip6,\r
1051 This->DriverBindingHandle,\r
1052 ControllerHandle,\r
1053 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1054 );\r
1055 if (EFI_ERROR (Status)) {\r
1056 goto ON_ERROR;\r
1057 }\r
1058\r
1059 //\r
1060 // Locate Ip6Config protocol, it's required to configure the default gateway address.\r
1061 //\r
1062 Status = gBS->OpenProtocol (\r
1063 ControllerHandle,\r
1064 &gEfiIp6ConfigProtocolGuid,\r
1065 (VOID **) &Private->Ip6Config,\r
1066 This->DriverBindingHandle,\r
1067 ControllerHandle,\r
1068 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1069 );\r
1070 if (EFI_ERROR (Status)) {\r
1071 goto ON_ERROR;\r
1072 }\r
1073\r
1074 //\r
1075 // Append IPv6 device path node.\r
1076 //\r
1077 Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));\r
1078 if (Node == NULL) {\r
1079 Status = EFI_OUT_OF_RESOURCES;\r
1080 goto ON_ERROR;\r
1081 }\r
1082 Node->Ipv6.Header.Type = MESSAGING_DEVICE_PATH;\r
1083 Node->Ipv6.Header.SubType = MSG_IPv6_DP;\r
1084 Node->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;\r
1085 SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH));\r
1086 DevicePath = AppendDevicePathNode(Private->ParentDevicePath, (EFI_DEVICE_PATH*) Node);\r
1087 FreePool(Node);\r
1088 if (DevicePath == NULL) {\r
1089 Status = EFI_OUT_OF_RESOURCES;\r
1090 goto ON_ERROR;\r
1091 }\r
1092\r
1093 //\r
1094 // Append URI device path node.\r
1095 //\r
1096 Node = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
1097 if (Node == NULL) {\r
1098 Status = EFI_OUT_OF_RESOURCES;\r
1099 goto ON_ERROR;\r
1100 }\r
1101 Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
1102 Node->DevPath.SubType = MSG_URI_DP;\r
1103 SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
1104 Private->Ip6Nic->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
1105 FreePool (Node);\r
1106 FreePool (DevicePath);\r
1107 if (Private->Ip6Nic->DevicePath == NULL) {\r
1108 Status = EFI_OUT_OF_RESOURCES;\r
1109 goto ON_ERROR;\r
1110 }\r
1111\r
1112 //\r
1113 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.\r
1114 //\r
1115 CopyMem (&Private->Ip6Nic->LoadFile, &gHttpBootDxeLoadFile, sizeof (Private->LoadFile));\r
1116 Status = gBS->InstallMultipleProtocolInterfaces (\r
1117 &Private->Ip6Nic->Controller,\r
1118 &gEfiLoadFileProtocolGuid,\r
1119 &Private->Ip6Nic->LoadFile,\r
1120 &gEfiDevicePathProtocolGuid,\r
1121 Private->Ip6Nic->DevicePath,\r
1122 NULL\r
1123 );\r
1124 if (EFI_ERROR (Status)) {\r
1125 goto ON_ERROR;\r
1126 }\r
1127\r
1128 //\r
1129 // Open the Caller Id child to setup a parent-child relationship between\r
1130 // real NIC handle and the HTTP boot child handle.\r
1131 //\r
1132 Status = gBS->OpenProtocol (\r
1133 ControllerHandle,\r
1134 &gEfiCallerIdGuid,\r
1135 (VOID **) &Id,\r
1136 This->DriverBindingHandle,\r
1137 Private->Ip6Nic->Controller,\r
1138 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1139 );\r
1140 if (EFI_ERROR (Status)) {\r
1141 goto ON_ERROR;\r
1142 }\r
1143\r
1144 return EFI_SUCCESS;\r
1145 \r
1146ON_ERROR:\r
ed247d86
JW
1147 if (FirstStart) {\r
1148 gBS->UninstallProtocolInterface (\r
1149 ControllerHandle,\r
1150 &gEfiCallerIdGuid,\r
1151 &Private->Id\r
1152 );\r
1153 }\r
b659408b 1154\r
fa848a40
FS
1155 HttpBootDestroyIp6Children(This, Private);\r
1156 HttpBootConfigFormUnload (Private);\r
ed247d86
JW
1157\r
1158 if (FirstStart && Private != NULL) {\r
1159 FreePool (Private);\r
1160 }\r
fa848a40
FS
1161\r
1162 return Status;\r
b659408b
ZL
1163}\r
1164\r
1165/**\r
1166 Stops a device controller or a bus controller.\r
1167 \r
1168 The Stop() function is designed to be invoked from the EFI boot service DisconnectController(). \r
1169 As a result, much of the error checking on the parameters to Stop() has been moved \r
1170 into this common boot service. It is legal to call Stop() from other locations, \r
1171 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
1172 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
1173 same driver's Start() function.\r
1174 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
1175 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
1176 Start() function, and the Start() function must have called OpenProtocol() on\r
1177 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
1178 \r
1179 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
1180 @param[in] ControllerHandle A handle to the device being stopped. The handle must \r
1181 support a bus specific I/O protocol for the driver \r
1182 to use to stop the device.\r
1183 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
1184 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL \r
1185 if NumberOfChildren is 0.\r
1186\r
1187 @retval EFI_SUCCESS The device was stopped.\r
1188 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
1189\r
1190**/\r
1191EFI_STATUS\r
1192EFIAPI\r
1193HttpBootIp6DxeDriverBindingStop (\r
1194 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1195 IN EFI_HANDLE ControllerHandle,\r
1196 IN UINTN NumberOfChildren,\r
1197 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
1198 )\r
1199{\r
1200 EFI_STATUS Status;\r
1201 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
1202 HTTP_BOOT_PRIVATE_DATA *Private;\r
1203 EFI_HANDLE NicHandle;\r
1204 UINT32 *Id;\r
1205\r
1206 //\r
1207 // Try to get the Load File Protocol from the controller handle.\r
1208 //\r
1209 Status = gBS->OpenProtocol (\r
1210 ControllerHandle,\r
1211 &gEfiLoadFileProtocolGuid,\r
1212 (VOID **) &LoadFile,\r
1213 This->DriverBindingHandle,\r
1214 ControllerHandle,\r
1215 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1216 );\r
1217 if (EFI_ERROR (Status)) {\r
1218 //\r
1219 // If failed, try to find the NIC handle for this controller.\r
1220 //\r
1221 NicHandle = HttpBootGetNicByIp6Children (ControllerHandle);\r
1222 if (NicHandle == NULL) {\r
1223 return EFI_SUCCESS;\r
1224 }\r
1225\r
1226 //\r
1227 // Try to retrieve the private data by the Caller Id Guid.\r
1228 //\r
1229 Status = gBS->OpenProtocol (\r
1230 NicHandle,\r
1231 &gEfiCallerIdGuid,\r
1232 (VOID **) &Id,\r
1233 This->DriverBindingHandle,\r
1234 ControllerHandle,\r
1235 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1236 );\r
1237 if (EFI_ERROR (Status)) {\r
1238 return Status;\r
1239 }\r
1240 Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id);\r
1241 } else {\r
1242 Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile);\r
1243 NicHandle = Private->Controller;\r
1244 }\r
1245\r
1246 //\r
1247 // Disable the HTTP boot function.\r
1248 //\r
1249 Status = HttpBootStop (Private);\r
1250 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {\r
1251 return Status;\r
1252 }\r
1253\r
1254 //\r
1255 // Destory all child instance and uninstall protocol interface.\r
1256 //\r
1257 HttpBootDestroyIp6Children (This, Private);\r
1258\r
1259 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
1260 //\r
1261 // Release the cached data.\r
1262 //\r
1263 HttpBootFreeCacheList (Private);\r
fa848a40
FS
1264\r
1265 //\r
1266 // Unload the config form.\r
1267 //\r
1268 HttpBootConfigFormUnload (Private);\r
1269\r
b659408b
ZL
1270 gBS->UninstallProtocolInterface (\r
1271 NicHandle,\r
1272 &gEfiCallerIdGuid,\r
1273 &Private->Id\r
1274 );\r
1275 FreePool (Private);\r
1276\r
1277 }\r
1278\r
1279 return EFI_SUCCESS;\r
1280}\r
1281/**\r
1282 This is the declaration of an EFI image entry point. This entry point is\r
1283 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
1284 both device drivers and bus drivers.\r
1285\r
1286 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
1287 @param[in] SystemTable A pointer to the EFI System Table.\r
1288\r
1289 @retval EFI_SUCCESS The operation completed successfully.\r
1290 @retval Others An unexpected error occurred.\r
1291\r
1292**/\r
1293EFI_STATUS\r
1294EFIAPI\r
1295HttpBootDxeDriverEntryPoint (\r
1296 IN EFI_HANDLE ImageHandle,\r
1297 IN EFI_SYSTEM_TABLE *SystemTable\r
1298 )\r
1299{\r
1300 EFI_STATUS Status;\r
fa848a40 1301\r
b659408b
ZL
1302 //\r
1303 // Install UEFI Driver Model protocol(s).\r
1304 //\r
1305 Status = EfiLibInstallDriverBindingComponentName2 (\r
1306 ImageHandle,\r
1307 SystemTable,\r
1308 &gHttpBootIp4DxeDriverBinding,\r
1309 ImageHandle,\r
1310 &gHttpBootDxeComponentName,\r
1311 &gHttpBootDxeComponentName2\r
1312 );\r
1313 if (EFI_ERROR (Status)) {\r
1314 return Status;\r
1315 }\r
1316 \r
1317 Status = EfiLibInstallDriverBindingComponentName2 (\r
1318 ImageHandle,\r
1319 SystemTable,\r
1320 &gHttpBootIp6DxeDriverBinding,\r
1321 NULL,\r
1322 &gHttpBootDxeComponentName,\r
1323 &gHttpBootDxeComponentName2\r
1324 );\r
1325 if (EFI_ERROR (Status)) {\r
1326 gBS->UninstallMultipleProtocolInterfaces(\r
1327 ImageHandle,\r
1328 &gEfiDriverBindingProtocolGuid,\r
1329 &gHttpBootIp4DxeDriverBinding,\r
1330 &gEfiComponentName2ProtocolGuid,\r
1331 &gHttpBootDxeComponentName2,\r
1332 &gEfiComponentNameProtocolGuid,\r
1333 &gHttpBootDxeComponentName,\r
1334 NULL\r
1335 );\r
1336 }\r
1337 return Status;\r
d933e70a
JW
1338}\r
1339\r