]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/HttpBootDxe/HttpBootDxe.c
BaseTools/Capsule: Do not support -o with --dump-info
[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
f75a7f56
LG
4Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>\r
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
d933e70a 7The full text of the license may be found at\r
f75a7f56
LG
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
d933e70a
JW
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
f75a7f56 78 //\r
ed247d86
JW
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
f75a7f56 124 }\r
ed247d86
JW
125\r
126 *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support;\r
127 FreePool (InfoBlock);\r
f75a7f56 128\r
ed247d86
JW
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 169 if (Private->Ip4Nic != NULL) {\r
f75a7f56 170\r
b659408b
ZL
171 gBS->CloseProtocol (\r
172 Private->Controller,\r
173 &gEfiCallerIdGuid,\r
174 This->DriverBindingHandle,\r
175 Private->Ip4Nic->Controller\r
176 );\r
f75a7f56 177\r
b659408b
ZL
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
f75a7f56 207\r
b659408b
ZL
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
f75a7f56 244\r
b659408b 245 if (Private->Ip6Nic != NULL) {\r
f75a7f56 246\r
b659408b
ZL
247 gBS->CloseProtocol (\r
248 Private->Controller,\r
249 &gEfiCallerIdGuid,\r
250 This->DriverBindingHandle,\r
251 Private->Ip6Nic->Controller\r
252 );\r
f75a7f56 253\r
b659408b
ZL
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
f75a7f56 268 Tests to see if this driver supports a given controller. If a child device is provided,\r
d933e70a
JW
269 it further tests to see if this driver supports creating a handle for the specified child device.\r
270\r
f75a7f56
LG
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
d933e70a
JW
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
f75a7f56
LG
286 @param[in] ControllerHandle The handle of the controller to test. This handle\r
287 must support a protocol interface that supplies\r
d933e70a 288 an I/O abstraction to the driver.\r
f75a7f56
LG
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
d933e70a
JW
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
f75a7f56 318\r
d933e70a
JW
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
f75a7f56
LG
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
d933e70a
JW
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
f75a7f56 370 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
d933e70a
JW
371\r
372 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
373 @param[in] ControllerHandle The handle of the controller to start. This handle\r
374 must support a protocol interface that supplies\r
d933e70a 375 an I/O abstraction to the driver.\r
f75a7f56
LG
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
d933e70a 383 RemainingDevicePath is created by this driver.\r
f75a7f56 384 If the first Device Path Node of RemainingDevicePath is\r
d933e70a
JW
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 423 FirstStart = TRUE;\r
f75a7f56 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
f75a7f56 486\r
b659408b 487 }\r
f75a7f56 488\r
b659408b
ZL
489 if (Private->Ip4Nic != NULL) {\r
490 //\r
491 // Already created before\r
492 //\r
493 return EFI_SUCCESS;\r
494 }\r
f75a7f56 495\r
b659408b
ZL
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
f75a7f56 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
f75a7f56 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
f75a7f56 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
f75a7f56 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
f75a7f56 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
f75a7f56 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
f75a7f56 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
f75a7f56 614\r
d933e70a 615 return EFI_SUCCESS;\r
f75a7f56 616\r
d933e70a 617ON_ERROR:\r
770f9aae
JW
618 if (Private != NULL) {\r
619 if (FirstStart) {\r
620 gBS->UninstallProtocolInterface (\r
621 ControllerHandle,\r
622 &gEfiCallerIdGuid,\r
623 &Private->Id\r
624 );\r
625 }\r
f75a7f56 626\r
770f9aae
JW
627 HttpBootDestroyIp4Children (This, Private);\r
628 HttpBootConfigFormUnload (Private);\r
ed247d86 629\r
770f9aae
JW
630 if (FirstStart) {\r
631 FreePool (Private);\r
632 }\r
ed247d86 633 }\r
d933e70a
JW
634\r
635 return Status;\r
636}\r
637\r
b659408b 638\r
d933e70a
JW
639/**\r
640 Stops a device controller or a bus controller.\r
f75a7f56
LG
641\r
642 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
643 As a result, much of the error checking on the parameters to Stop() has been moved\r
644 into this common boot service. It is legal to call Stop() from other locations,\r
d933e70a
JW
645 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
646 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
647 same driver's Start() function.\r
648 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
649 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
650 Start() function, and the Start() function must have called OpenProtocol() on\r
651 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
f75a7f56 652\r
d933e70a 653 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
654 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
655 support a bus specific I/O protocol for the driver\r
d933e70a
JW
656 to use to stop the device.\r
657 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
f75a7f56 658 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
d933e70a
JW
659 if NumberOfChildren is 0.\r
660\r
661 @retval EFI_SUCCESS The device was stopped.\r
662 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
663\r
664**/\r
665EFI_STATUS\r
666EFIAPI\r
667HttpBootIp4DxeDriverBindingStop (\r
668 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
669 IN EFI_HANDLE ControllerHandle,\r
670 IN UINTN NumberOfChildren,\r
671 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
672 )\r
673{\r
674 EFI_STATUS Status;\r
675 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
676 HTTP_BOOT_PRIVATE_DATA *Private;\r
677 EFI_HANDLE NicHandle;\r
678 UINT32 *Id;\r
679\r
680 //\r
681 // Try to get the Load File Protocol from the controller handle.\r
682 //\r
683 Status = gBS->OpenProtocol (\r
684 ControllerHandle,\r
685 &gEfiLoadFileProtocolGuid,\r
686 (VOID **) &LoadFile,\r
687 This->DriverBindingHandle,\r
688 ControllerHandle,\r
689 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
690 );\r
691 if (EFI_ERROR (Status)) {\r
692 //\r
693 // If failed, try to find the NIC handle for this controller.\r
694 //\r
695 NicHandle = HttpBootGetNicByIp4Children (ControllerHandle);\r
696 if (NicHandle == NULL) {\r
697 return EFI_SUCCESS;\r
698 }\r
699\r
700 //\r
701 // Try to retrieve the private data by the Caller Id Guid.\r
702 //\r
703 Status = gBS->OpenProtocol (\r
704 NicHandle,\r
705 &gEfiCallerIdGuid,\r
706 (VOID **) &Id,\r
707 This->DriverBindingHandle,\r
708 ControllerHandle,\r
709 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
710 );\r
711 if (EFI_ERROR (Status)) {\r
712 return Status;\r
713 }\r
714 Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id);\r
715 } else {\r
716 Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile);\r
717 NicHandle = Private->Controller;\r
718 }\r
719\r
720 //\r
721 // Disable the HTTP boot function.\r
722 //\r
723 Status = HttpBootStop (Private);\r
724 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {\r
725 return Status;\r
726 }\r
727\r
728 //\r
729 // Destory all child instance and uninstall protocol interface.\r
730 //\r
731 HttpBootDestroyIp4Children (This, Private);\r
f75a7f56 732\r
b659408b
ZL
733 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
734 //\r
735 // Release the cached data.\r
736 //\r
737 HttpBootFreeCacheList (Private);\r
fa848a40
FS
738\r
739 //\r
740 // Unload the config form.\r
741 //\r
742 HttpBootConfigFormUnload (Private);\r
f75a7f56 743\r
b659408b
ZL
744 gBS->UninstallProtocolInterface (\r
745 NicHandle,\r
746 &gEfiCallerIdGuid,\r
747 &Private->Id\r
748 );\r
749 FreePool (Private);\r
d933e70a 750\r
b659408b 751 }\r
d933e70a
JW
752\r
753 return EFI_SUCCESS;\r
754}\r
755\r
756/**\r
f75a7f56 757 Tests to see if this driver supports a given controller. If a child device is provided,\r
b659408b 758 it further tests to see if this driver supports creating a handle for the specified child device.\r
d933e70a 759\r
f75a7f56
LG
760 This function checks to see if the driver specified by This supports the device specified by\r
761 ControllerHandle. Drivers will typically use the device path attached to\r
762 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
763 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
764 may be called many times during platform initialization. In order to reduce boot times, the tests\r
765 performed by this function must be very small, and take as little time as possible to execute. This\r
766 function must not change the state of any hardware devices, and this function must be aware that the\r
767 device specified by ControllerHandle may already be managed by the same driver or a\r
768 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
769 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
770 Because ControllerHandle may have been previously started by the same driver, if a protocol is\r
771 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
b659408b 772 to guarantee the state of ControllerHandle is not modified by this function.\r
d933e70a 773\r
b659408b 774 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
775 @param[in] ControllerHandle The handle of the controller to test. This handle\r
776 must support a protocol interface that supplies\r
b659408b 777 an I/O abstraction to the driver.\r
f75a7f56
LG
778 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
779 parameter is ignored by device drivers, and is optional for bus\r
780 drivers. For bus drivers, if this parameter is not NULL, then\r
781 the bus driver must determine if the bus controller specified\r
782 by ControllerHandle and the child controller specified\r
783 by RemainingDevicePath are both supported by this\r
b659408b 784 bus driver.\r
d933e70a 785\r
b659408b
ZL
786 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
787 RemainingDevicePath is supported by the driver specified by This.\r
788 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
789 RemainingDevicePath is already being managed by the driver\r
790 specified by This.\r
791 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
792 RemainingDevicePath is already being managed by a different\r
793 driver or an application that requires exclusive access.\r
794 Currently not implemented.\r
795 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
796 RemainingDevicePath is not supported by the driver specified by This.\r
d933e70a
JW
797**/\r
798EFI_STATUS\r
799EFIAPI\r
b659408b
ZL
800HttpBootIp6DxeDriverBindingSupported (\r
801 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
802 IN EFI_HANDLE ControllerHandle,\r
803 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
d933e70a
JW
804 )\r
805{\r
b659408b 806 EFI_STATUS Status;\r
f75a7f56 807\r
d933e70a 808 //\r
b659408b 809 // Try to open the DHCP6, HTTP and Device Path protocol.\r
d933e70a 810 //\r
b659408b
ZL
811 Status = gBS->OpenProtocol (\r
812 ControllerHandle,\r
813 &gEfiDhcp6ServiceBindingProtocolGuid,\r
814 NULL,\r
815 This->DriverBindingHandle,\r
816 ControllerHandle,\r
817 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
818 );\r
819 if (EFI_ERROR (Status)) {\r
820 return Status;\r
821 }\r
822\r
823 Status = gBS->OpenProtocol (\r
824 ControllerHandle,\r
825 &gEfiHttpServiceBindingProtocolGuid,\r
826 NULL,\r
827 This->DriverBindingHandle,\r
828 ControllerHandle,\r
829 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
830 );\r
831 if (EFI_ERROR (Status)) {\r
832 return Status;\r
833 }\r
834\r
835 Status = gBS->OpenProtocol (\r
836 ControllerHandle,\r
837 &gEfiDevicePathProtocolGuid,\r
838 NULL,\r
839 This->DriverBindingHandle,\r
840 ControllerHandle,\r
841 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
842 );\r
843\r
844 return Status;\r
845\r
846}\r
847\r
848/**\r
849 Starts a device controller or a bus controller.\r
850\r
851 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
f75a7f56
LG
852 As a result, much of the error checking on the parameters to Start() has been moved into this\r
853 common boot service. It is legal to call Start() from other locations,\r
b659408b
ZL
854 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
855 1. ControllerHandle must be a valid EFI_HANDLE.\r
856 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
857 EFI_DEVICE_PATH_PROTOCOL.\r
858 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
f75a7f56 859 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
b659408b
ZL
860\r
861 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
862 @param[in] ControllerHandle The handle of the controller to start. This handle\r
863 must support a protocol interface that supplies\r
b659408b 864 an I/O abstraction to the driver.\r
f75a7f56
LG
865 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
866 parameter is ignored by device drivers, and is optional for bus\r
867 drivers. For a bus driver, if this parameter is NULL, then handles\r
868 for all the children of Controller are created by this driver.\r
869 If this parameter is not NULL and the first Device Path Node is\r
870 not the End of Device Path Node, then only the handle for the\r
871 child device specified by the first Device Path Node of\r
b659408b 872 RemainingDevicePath is created by this driver.\r
f75a7f56 873 If the first Device Path Node of RemainingDevicePath is\r
b659408b
ZL
874 the End of Device Path Node, no child handle is created by this\r
875 driver.\r
876\r
877 @retval EFI_SUCCESS The device was started.\r
878 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
879 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
880 @retval Others The driver failded to start the device.\r
881\r
882**/\r
883EFI_STATUS\r
884EFIAPI\r
885HttpBootIp6DxeDriverBindingStart (\r
886 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
887 IN EFI_HANDLE ControllerHandle,\r
888 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
889 )\r
890{\r
891 EFI_STATUS Status;\r
892 HTTP_BOOT_PRIVATE_DATA *Private;\r
893 EFI_DEV_PATH *Node;\r
894 EFI_DEVICE_PATH_PROTOCOL *DevicePath;\r
895 UINT32 *Id;\r
ed247d86
JW
896 BOOLEAN Ipv6Available;\r
897 BOOLEAN FirstStart;\r
898\r
899 FirstStart = FALSE;\r
f75a7f56 900\r
b659408b
ZL
901 Status = gBS->OpenProtocol (\r
902 ControllerHandle,\r
903 &gEfiCallerIdGuid,\r
904 (VOID **) &Id,\r
905 This->DriverBindingHandle,\r
906 ControllerHandle,\r
907 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
908 );\r
f75a7f56 909\r
b659408b 910 if (!EFI_ERROR (Status)) {\r
75372581 911 Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID(Id);\r
b659408b 912 } else {\r
ed247d86 913 FirstStart = TRUE;\r
f75a7f56 914\r
b659408b
ZL
915 //\r
916 // Initialize the private data structure.\r
917 //\r
918 Private = AllocateZeroPool (sizeof (HTTP_BOOT_PRIVATE_DATA));\r
919 if (Private == NULL) {\r
920 return EFI_OUT_OF_RESOURCES;\r
921 }\r
922 Private->Signature = HTTP_BOOT_PRIVATE_DATA_SIGNATURE;\r
923 Private->Controller = ControllerHandle;\r
b659408b
ZL
924 InitializeListHead (&Private->CacheList);\r
925 //\r
926 // Get the NII interface if it exists, it's not required.\r
927 //\r
928 Status = gBS->OpenProtocol (\r
929 ControllerHandle,\r
930 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
931 (VOID **) &Private->Nii,\r
932 This->DriverBindingHandle,\r
933 ControllerHandle,\r
934 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
935 );\r
936 if (EFI_ERROR (Status)) {\r
937 Private->Nii = NULL;\r
938 }\r
939\r
940 //\r
941 // Open Device Path Protocol to prepare for appending IP and URI node.\r
942 //\r
943 Status = gBS->OpenProtocol (\r
944 ControllerHandle,\r
945 &gEfiDevicePathProtocolGuid,\r
946 (VOID **) &Private->ParentDevicePath,\r
947 This->DriverBindingHandle,\r
948 ControllerHandle,\r
949 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
950 );\r
951 if (EFI_ERROR (Status)) {\r
952 goto ON_ERROR;\r
953 }\r
954\r
fa848a40
FS
955 //\r
956 // Initialize the HII configuration form.\r
957 //\r
958 Status = HttpBootConfigFormInit (Private);\r
959 if (EFI_ERROR (Status)) {\r
960 goto ON_ERROR;\r
961 }\r
962\r
b659408b
ZL
963 //\r
964 // Install a protocol with Caller Id Guid to the NIC, this is just to build the relationship between\r
965 // NIC handle and the private data.\r
966 //\r
967 Status = gBS->InstallProtocolInterface (\r
968 &ControllerHandle,\r
969 &gEfiCallerIdGuid,\r
970 EFI_NATIVE_INTERFACE,\r
971 &Private->Id\r
972 );\r
973 if (EFI_ERROR (Status)) {\r
974 goto ON_ERROR;\r
975 }\r
f75a7f56 976\r
b659408b 977 }\r
ed247d86
JW
978\r
979 //\r
980 // Set IPv6 available flag.\r
f75a7f56 981 //\r
ed247d86
JW
982 Status = HttpBootCheckIpv6Support (Private, &Ipv6Available);\r
983 if (EFI_ERROR (Status)) {\r
984 //\r
f75a7f56 985 // Fail to get the data whether UNDI supports IPv6.\r
ed247d86
JW
986 // Set default value to TRUE.\r
987 //\r
988 Ipv6Available = TRUE;\r
989 }\r
990\r
991 if (!Ipv6Available) {\r
992 Status = EFI_UNSUPPORTED;\r
993 goto ON_ERROR;\r
994 }\r
f75a7f56 995\r
b659408b
ZL
996 if (Private->Ip6Nic != NULL) {\r
997 //\r
998 // Already created before\r
999 //\r
1000 return EFI_SUCCESS;\r
1001 }\r
f75a7f56 1002\r
b659408b
ZL
1003 Private->Ip6Nic = AllocateZeroPool (sizeof (HTTP_BOOT_VIRTUAL_NIC));\r
1004 if (Private->Ip6Nic == NULL) {\r
ed247d86
JW
1005 Status = EFI_OUT_OF_RESOURCES;\r
1006 goto ON_ERROR;\r
b659408b 1007 }\r
75372581
FS
1008 Private->Ip6Nic->Private = Private;\r
1009 Private->Ip6Nic->ImageHandle = This->DriverBindingHandle;\r
1010 Private->Ip6Nic->Signature = HTTP_BOOT_VIRTUAL_NIC_SIGNATURE;\r
f75a7f56 1011\r
b659408b
ZL
1012 //\r
1013 // Create Dhcp6 child and open Dhcp6 protocol\r
1014 Status = NetLibCreateServiceChild (\r
1015 ControllerHandle,\r
1016 This->DriverBindingHandle,\r
1017 &gEfiDhcp6ServiceBindingProtocolGuid,\r
1018 &Private->Dhcp6Child\r
1019 );\r
1020 if (EFI_ERROR (Status)) {\r
1021 goto ON_ERROR;\r
1022 }\r
1023\r
1024 Status = gBS->OpenProtocol (\r
1025 Private->Dhcp6Child,\r
1026 &gEfiDhcp6ProtocolGuid,\r
1027 (VOID **) &Private->Dhcp6,\r
1028 This->DriverBindingHandle,\r
1029 ControllerHandle,\r
1030 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1031 );\r
1032 if (EFI_ERROR (Status)) {\r
1033 goto ON_ERROR;\r
1034 }\r
1035\r
1036 //\r
1037 // Create Ip6 child and open Ip6 protocol for background ICMP packets.\r
1038 //\r
1039 Status = NetLibCreateServiceChild (\r
1040 ControllerHandle,\r
1041 This->DriverBindingHandle,\r
1042 &gEfiIp6ServiceBindingProtocolGuid,\r
1043 &Private->Ip6Child\r
1044 );\r
1045 if (EFI_ERROR (Status)) {\r
1046 goto ON_ERROR;\r
1047 }\r
1048\r
1049 Status = gBS->OpenProtocol (\r
1050 Private->Ip6Child,\r
1051 &gEfiIp6ProtocolGuid,\r
1052 (VOID **) &Private->Ip6,\r
1053 This->DriverBindingHandle,\r
1054 ControllerHandle,\r
1055 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1056 );\r
1057 if (EFI_ERROR (Status)) {\r
1058 goto ON_ERROR;\r
1059 }\r
1060\r
1061 //\r
1062 // Locate Ip6Config protocol, it's required to configure the default gateway address.\r
1063 //\r
1064 Status = gBS->OpenProtocol (\r
1065 ControllerHandle,\r
1066 &gEfiIp6ConfigProtocolGuid,\r
1067 (VOID **) &Private->Ip6Config,\r
1068 This->DriverBindingHandle,\r
1069 ControllerHandle,\r
1070 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1071 );\r
1072 if (EFI_ERROR (Status)) {\r
1073 goto ON_ERROR;\r
1074 }\r
1075\r
1076 //\r
1077 // Append IPv6 device path node.\r
1078 //\r
1079 Node = AllocateZeroPool (sizeof (IPv6_DEVICE_PATH));\r
1080 if (Node == NULL) {\r
1081 Status = EFI_OUT_OF_RESOURCES;\r
1082 goto ON_ERROR;\r
1083 }\r
1084 Node->Ipv6.Header.Type = MESSAGING_DEVICE_PATH;\r
1085 Node->Ipv6.Header.SubType = MSG_IPv6_DP;\r
1086 Node->Ipv6.PrefixLength = IP6_PREFIX_LENGTH;\r
1087 SetDevicePathNodeLength (Node, sizeof (IPv6_DEVICE_PATH));\r
1088 DevicePath = AppendDevicePathNode(Private->ParentDevicePath, (EFI_DEVICE_PATH*) Node);\r
1089 FreePool(Node);\r
1090 if (DevicePath == NULL) {\r
1091 Status = EFI_OUT_OF_RESOURCES;\r
1092 goto ON_ERROR;\r
1093 }\r
1094\r
1095 //\r
1096 // Append URI device path node.\r
1097 //\r
1098 Node = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
1099 if (Node == NULL) {\r
1100 Status = EFI_OUT_OF_RESOURCES;\r
1101 goto ON_ERROR;\r
1102 }\r
1103 Node->DevPath.Type = MESSAGING_DEVICE_PATH;\r
1104 Node->DevPath.SubType = MSG_URI_DP;\r
1105 SetDevicePathNodeLength (Node, sizeof (EFI_DEVICE_PATH_PROTOCOL));\r
1106 Private->Ip6Nic->DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL*) Node);\r
1107 FreePool (Node);\r
1108 FreePool (DevicePath);\r
1109 if (Private->Ip6Nic->DevicePath == NULL) {\r
1110 Status = EFI_OUT_OF_RESOURCES;\r
1111 goto ON_ERROR;\r
1112 }\r
1113\r
1114 //\r
1115 // Create a child handle for the HTTP boot and install DevPath and Load file protocol on it.\r
1116 //\r
1117 CopyMem (&Private->Ip6Nic->LoadFile, &gHttpBootDxeLoadFile, sizeof (Private->LoadFile));\r
1118 Status = gBS->InstallMultipleProtocolInterfaces (\r
1119 &Private->Ip6Nic->Controller,\r
1120 &gEfiLoadFileProtocolGuid,\r
1121 &Private->Ip6Nic->LoadFile,\r
1122 &gEfiDevicePathProtocolGuid,\r
1123 Private->Ip6Nic->DevicePath,\r
1124 NULL\r
1125 );\r
1126 if (EFI_ERROR (Status)) {\r
1127 goto ON_ERROR;\r
1128 }\r
1129\r
1130 //\r
1131 // Open the Caller Id child to setup a parent-child relationship between\r
1132 // real NIC handle and the HTTP boot child handle.\r
1133 //\r
1134 Status = gBS->OpenProtocol (\r
1135 ControllerHandle,\r
1136 &gEfiCallerIdGuid,\r
1137 (VOID **) &Id,\r
1138 This->DriverBindingHandle,\r
1139 Private->Ip6Nic->Controller,\r
1140 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1141 );\r
1142 if (EFI_ERROR (Status)) {\r
1143 goto ON_ERROR;\r
1144 }\r
1145\r
1146 return EFI_SUCCESS;\r
f75a7f56 1147\r
b659408b 1148ON_ERROR:\r
770f9aae
JW
1149 if (Private != NULL) {\r
1150 if (FirstStart) {\r
1151 gBS->UninstallProtocolInterface (\r
1152 ControllerHandle,\r
1153 &gEfiCallerIdGuid,\r
1154 &Private->Id\r
1155 );\r
1156 }\r
b659408b 1157\r
770f9aae
JW
1158 HttpBootDestroyIp6Children(This, Private);\r
1159 HttpBootConfigFormUnload (Private);\r
ed247d86 1160\r
770f9aae
JW
1161 if (FirstStart) {\r
1162 FreePool (Private);\r
1163 }\r
ed247d86 1164 }\r
fa848a40
FS
1165\r
1166 return Status;\r
b659408b
ZL
1167}\r
1168\r
1169/**\r
1170 Stops a device controller or a bus controller.\r
f75a7f56
LG
1171\r
1172 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
1173 As a result, much of the error checking on the parameters to Stop() has been moved\r
1174 into this common boot service. It is legal to call Stop() from other locations,\r
b659408b
ZL
1175 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
1176 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
1177 same driver's Start() function.\r
1178 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
1179 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
1180 Start() function, and the Start() function must have called OpenProtocol() on\r
1181 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
f75a7f56 1182\r
b659408b 1183 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
f75a7f56
LG
1184 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
1185 support a bus specific I/O protocol for the driver\r
b659408b
ZL
1186 to use to stop the device.\r
1187 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
f75a7f56 1188 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
b659408b
ZL
1189 if NumberOfChildren is 0.\r
1190\r
1191 @retval EFI_SUCCESS The device was stopped.\r
1192 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
1193\r
1194**/\r
1195EFI_STATUS\r
1196EFIAPI\r
1197HttpBootIp6DxeDriverBindingStop (\r
1198 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1199 IN EFI_HANDLE ControllerHandle,\r
1200 IN UINTN NumberOfChildren,\r
1201 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
1202 )\r
1203{\r
1204 EFI_STATUS Status;\r
1205 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
1206 HTTP_BOOT_PRIVATE_DATA *Private;\r
1207 EFI_HANDLE NicHandle;\r
1208 UINT32 *Id;\r
1209\r
1210 //\r
1211 // Try to get the Load File Protocol from the controller handle.\r
1212 //\r
1213 Status = gBS->OpenProtocol (\r
1214 ControllerHandle,\r
1215 &gEfiLoadFileProtocolGuid,\r
1216 (VOID **) &LoadFile,\r
1217 This->DriverBindingHandle,\r
1218 ControllerHandle,\r
1219 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1220 );\r
1221 if (EFI_ERROR (Status)) {\r
1222 //\r
1223 // If failed, try to find the NIC handle for this controller.\r
1224 //\r
1225 NicHandle = HttpBootGetNicByIp6Children (ControllerHandle);\r
1226 if (NicHandle == NULL) {\r
1227 return EFI_SUCCESS;\r
1228 }\r
1229\r
1230 //\r
1231 // Try to retrieve the private data by the Caller Id Guid.\r
1232 //\r
1233 Status = gBS->OpenProtocol (\r
1234 NicHandle,\r
1235 &gEfiCallerIdGuid,\r
1236 (VOID **) &Id,\r
1237 This->DriverBindingHandle,\r
1238 ControllerHandle,\r
1239 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1240 );\r
1241 if (EFI_ERROR (Status)) {\r
1242 return Status;\r
1243 }\r
1244 Private = HTTP_BOOT_PRIVATE_DATA_FROM_ID (Id);\r
1245 } else {\r
1246 Private = HTTP_BOOT_PRIVATE_DATA_FROM_LOADFILE (LoadFile);\r
1247 NicHandle = Private->Controller;\r
1248 }\r
1249\r
1250 //\r
1251 // Disable the HTTP boot function.\r
1252 //\r
1253 Status = HttpBootStop (Private);\r
1254 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {\r
1255 return Status;\r
1256 }\r
1257\r
1258 //\r
1259 // Destory all child instance and uninstall protocol interface.\r
1260 //\r
1261 HttpBootDestroyIp6Children (This, Private);\r
1262\r
1263 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
1264 //\r
1265 // Release the cached data.\r
1266 //\r
1267 HttpBootFreeCacheList (Private);\r
fa848a40
FS
1268\r
1269 //\r
1270 // Unload the config form.\r
1271 //\r
1272 HttpBootConfigFormUnload (Private);\r
1273\r
b659408b
ZL
1274 gBS->UninstallProtocolInterface (\r
1275 NicHandle,\r
1276 &gEfiCallerIdGuid,\r
1277 &Private->Id\r
1278 );\r
1279 FreePool (Private);\r
1280\r
1281 }\r
1282\r
1283 return EFI_SUCCESS;\r
1284}\r
1285/**\r
1286 This is the declaration of an EFI image entry point. This entry point is\r
1287 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
1288 both device drivers and bus drivers.\r
1289\r
1290 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
1291 @param[in] SystemTable A pointer to the EFI System Table.\r
1292\r
1293 @retval EFI_SUCCESS The operation completed successfully.\r
1294 @retval Others An unexpected error occurred.\r
1295\r
1296**/\r
1297EFI_STATUS\r
1298EFIAPI\r
1299HttpBootDxeDriverEntryPoint (\r
1300 IN EFI_HANDLE ImageHandle,\r
1301 IN EFI_SYSTEM_TABLE *SystemTable\r
1302 )\r
1303{\r
1304 EFI_STATUS Status;\r
fa848a40 1305\r
b659408b
ZL
1306 //\r
1307 // Install UEFI Driver Model protocol(s).\r
1308 //\r
1309 Status = EfiLibInstallDriverBindingComponentName2 (\r
1310 ImageHandle,\r
1311 SystemTable,\r
1312 &gHttpBootIp4DxeDriverBinding,\r
1313 ImageHandle,\r
1314 &gHttpBootDxeComponentName,\r
1315 &gHttpBootDxeComponentName2\r
1316 );\r
1317 if (EFI_ERROR (Status)) {\r
1318 return Status;\r
1319 }\r
f75a7f56 1320\r
b659408b
ZL
1321 Status = EfiLibInstallDriverBindingComponentName2 (\r
1322 ImageHandle,\r
1323 SystemTable,\r
1324 &gHttpBootIp6DxeDriverBinding,\r
1325 NULL,\r
1326 &gHttpBootDxeComponentName,\r
1327 &gHttpBootDxeComponentName2\r
1328 );\r
1329 if (EFI_ERROR (Status)) {\r
1330 gBS->UninstallMultipleProtocolInterfaces(\r
1331 ImageHandle,\r
1332 &gEfiDriverBindingProtocolGuid,\r
1333 &gHttpBootIp4DxeDriverBinding,\r
1334 &gEfiComponentName2ProtocolGuid,\r
1335 &gHttpBootDxeComponentName2,\r
1336 &gEfiComponentNameProtocolGuid,\r
1337 &gHttpBootDxeComponentName,\r
1338 NULL\r
1339 );\r
1340 }\r
1341 return Status;\r
d933e70a
JW
1342}\r
1343\r