]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
Update comments for PI 1.2 SMM support.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDriver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Driver Binding functions implementationfor for UefiPxeBc Driver.\r
3\r
4 Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php.\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "PxeBcImpl.h"\r
17\r
18\r
19EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {\r
20 PxeBcDriverBindingSupported,\r
21 PxeBcDriverBindingStart,\r
22 PxeBcDriverBindingStop,\r
23 0xa,\r
24 NULL,\r
25 NULL\r
26};\r
27\r
28\r
29/**\r
30 Get the Nic handle using any child handle in the IPv4 stack.\r
31\r
32 @param[in] ControllerHandle Pointer to child handle over IPv4.\r
33\r
34 @return NicHandle The pointer to the Nic handle.\r
35\r
36**/\r
37EFI_HANDLE\r
38PxeBcGetNicByIp4Children (\r
39 IN EFI_HANDLE ControllerHandle\r
40 )\r
41{\r
42 EFI_HANDLE NicHandle;\r
43\r
44 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
45 if (NicHandle == NULL) {\r
46 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);\r
47 if (NicHandle == NULL) {\r
48 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);\r
49 if (NicHandle == NULL) {\r
50 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
51 if (NicHandle == NULL) {\r
52 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);\r
53 if (NicHandle == NULL) {\r
54 return NULL;\r
55 }\r
56 }\r
57 }\r
58 }\r
59 }\r
60\r
61 return NicHandle;\r
62}\r
63\r
64\r
65/**\r
66 Get the Nic handle using any child handle in the IPv6 stack.\r
67\r
68 @param[in] ControllerHandle Pointer to child handle over IPv6.\r
69\r
70 @return NicHandle The pointer to the Nic handle.\r
71\r
72**/\r
73EFI_HANDLE\r
74PxeBcGetNicByIp6Children (\r
75 IN EFI_HANDLE ControllerHandle\r
76 )\r
77{\r
78 EFI_HANDLE NicHandle;\r
79\r
80 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp6ProtocolGuid);\r
81 if (NicHandle == NULL) {\r
82 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);\r
83 if (NicHandle == NULL) {\r
84 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
85 if (NicHandle == NULL) {\r
86 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp6ProtocolGuid);\r
87 if (NicHandle == NULL) {\r
88 return NULL;\r
89 }\r
90 }\r
91 }\r
92 }\r
93\r
94 return NicHandle;\r
95}\r
96\r
97\r
98/**\r
99 Destroy the opened instances based on IPv4.\r
100\r
101 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.\r
102 @param[in] Private Pointer to PXEBC_PRIVATE_DATA.\r
103\r
104**/\r
105VOID\r
106PxeBcDestroyIp4Children (\r
107 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
108 IN PXEBC_PRIVATE_DATA *Private\r
109 )\r
110{\r
111 ASSERT(Private != NULL);\r
112\r
113 if (Private->ArpChild != NULL) {\r
114 //\r
115 // Close Arp for PxeBc->Arp and destroy the instance.\r
116 //\r
117 gBS->CloseProtocol (\r
118 Private->ArpChild,\r
119 &gEfiArpProtocolGuid,\r
120 This->DriverBindingHandle,\r
121 Private->Controller\r
122 );\r
123\r
124 NetLibDestroyServiceChild (\r
125 Private->Controller,\r
126 This->DriverBindingHandle,\r
127 &gEfiArpServiceBindingProtocolGuid,\r
128 Private->ArpChild\r
129 );\r
130 }\r
131\r
132 if (Private->Ip4Child != NULL) {\r
133 //\r
134 // Close Ip4 for background ICMP error message and destroy the instance.\r
135 //\r
136 gBS->CloseProtocol (\r
137 Private->Ip4Child,\r
138 &gEfiIp4ProtocolGuid,\r
139 This->DriverBindingHandle,\r
140 Private->Controller\r
141 );\r
142\r
143 NetLibDestroyServiceChild (\r
144 Private->Controller,\r
145 This->DriverBindingHandle,\r
146 &gEfiIp4ServiceBindingProtocolGuid,\r
147 Private->Ip4Child\r
148 );\r
149 }\r
150\r
151 if (Private->Udp4WriteChild != NULL) {\r
152 //\r
153 // Close Udp4 for PxeBc->UdpWrite and destroy the instance.\r
154 //\r
155 gBS->CloseProtocol (\r
156 Private->Udp4WriteChild,\r
157 &gEfiUdp4ProtocolGuid,\r
158 This->DriverBindingHandle,\r
159 Private->Controller\r
160 );\r
161\r
162 NetLibDestroyServiceChild (\r
163 Private->Controller,\r
164 This->DriverBindingHandle,\r
165 &gEfiUdp4ServiceBindingProtocolGuid,\r
166 Private->Udp4WriteChild\r
167 );\r
168 }\r
169\r
170 if (Private->Udp4ReadChild != NULL) {\r
171 //\r
172 // Close Udp4 for PxeBc->UdpRead and destroy the instance.\r
173 //\r
174 gBS->CloseProtocol (\r
175 Private->Udp4ReadChild,\r
176 &gEfiUdp4ProtocolGuid,\r
177 This->DriverBindingHandle,\r
178 Private->Controller\r
179 );\r
180\r
181 NetLibDestroyServiceChild (\r
182 Private->Controller,\r
183 This->DriverBindingHandle,\r
184 &gEfiUdp4ServiceBindingProtocolGuid,\r
185 Private->Udp4ReadChild\r
186 );\r
187 }\r
188\r
189 if (Private->Mtftp4Child != NULL) {\r
190 //\r
191 // Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance.\r
192 //\r
193 gBS->CloseProtocol (\r
194 Private->Mtftp4Child,\r
195 &gEfiMtftp4ProtocolGuid,\r
196 This->DriverBindingHandle,\r
197 Private->Controller\r
198 );\r
199\r
200 NetLibDestroyServiceChild (\r
201 Private->Controller,\r
202 This->DriverBindingHandle,\r
203 &gEfiMtftp4ServiceBindingProtocolGuid,\r
204 Private->Mtftp4Child\r
205 );\r
206 }\r
207\r
208 if (Private->Dhcp4Child != NULL) {\r
209 //\r
210 // Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance.\r
211 //\r
212 gBS->CloseProtocol (\r
213 Private->Dhcp4Child,\r
214 &gEfiDhcp4ProtocolGuid,\r
215 This->DriverBindingHandle,\r
216 Private->Controller\r
217 );\r
218\r
219 NetLibDestroyServiceChild (\r
220 Private->Controller,\r
221 This->DriverBindingHandle,\r
222 &gEfiDhcp4ServiceBindingProtocolGuid,\r
223 Private->Dhcp4Child\r
224 );\r
225 }\r
226\r
227 if (Private->Ip4Nic != NULL) {\r
228 //\r
229 // Close PxeBc from the parent Nic handle and destroy the virtual handle.\r
230 //\r
231 gBS->CloseProtocol (\r
232 Private->Controller,\r
233 &gEfiPxeBaseCodeProtocolGuid,\r
234 This->DriverBindingHandle,\r
235 Private->Ip4Nic->Controller\r
236 );\r
237\r
238 gBS->UninstallMultipleProtocolInterfaces (\r
239 Private->Ip4Nic->Controller,\r
240 &gEfiDevicePathProtocolGuid,\r
241 Private->Ip4Nic->DevicePath,\r
242 &gEfiLoadFileProtocolGuid,\r
243 &Private->Ip4Nic->LoadFile,\r
244 NULL\r
245 );\r
246 FreePool (Private->Ip4Nic);\r
247 }\r
248\r
249 Private->ArpChild = NULL;\r
250 Private->Ip4Child = NULL;\r
251 Private->Udp4WriteChild = NULL;\r
252 Private->Udp4ReadChild = NULL;\r
253 Private->Mtftp4Child = NULL;\r
254 Private->Dhcp4Child = NULL;\r
255 Private->Ip4Nic = NULL;\r
256}\r
257\r
258\r
259/**\r
260 Destroy the opened instances based on IPv6.\r
261\r
262 @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL.\r
263 @param[in] Private Pointer to PXEBC_PRIVATE_DATA.\r
264\r
265**/\r
266VOID\r
267PxeBcDestroyIp6Children (\r
268 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
269 IN PXEBC_PRIVATE_DATA *Private\r
270 )\r
271{\r
272 ASSERT(Private != NULL);\r
273\r
274 if (Private->Ip6Child != NULL) {\r
275 //\r
276 // Close Ip6 for Ip6->Ip6Config and destroy the instance.\r
277 //\r
278 gBS->CloseProtocol (\r
279 Private->Ip6Child,\r
280 &gEfiIp6ProtocolGuid,\r
281 This->DriverBindingHandle,\r
282 Private->Controller\r
283 );\r
284\r
285 NetLibDestroyServiceChild (\r
286 Private->Controller,\r
287 This->DriverBindingHandle,\r
288 &gEfiIp6ServiceBindingProtocolGuid,\r
289 Private->Ip6Child\r
290 );\r
291 }\r
292\r
293 if (Private->Udp6WriteChild != NULL) {\r
294 //\r
295 // Close Udp6 for PxeBc->UdpWrite and destroy the instance.\r
296 //\r
297 gBS->CloseProtocol (\r
298 Private->Udp6WriteChild,\r
299 &gEfiUdp6ProtocolGuid,\r
300 This->DriverBindingHandle,\r
301 Private->Controller\r
302 );\r
303 NetLibDestroyServiceChild (\r
304 Private->Controller,\r
305 This->DriverBindingHandle,\r
306 &gEfiUdp6ServiceBindingProtocolGuid,\r
307 Private->Udp6WriteChild\r
308 );\r
309 }\r
310\r
311 if (Private->Udp6ReadChild != NULL) {\r
312 //\r
313 // Close Udp6 for PxeBc->UdpRead and destroy the instance.\r
314 //\r
315 gBS->CloseProtocol (\r
316 Private->Udp6ReadChild,\r
317 &gEfiUdp6ProtocolGuid,\r
318 This->DriverBindingHandle,\r
319 Private->Controller\r
320 );\r
321 NetLibDestroyServiceChild (\r
322 Private->Controller,\r
323 This->DriverBindingHandle,\r
324 &gEfiUdp6ServiceBindingProtocolGuid,\r
325 Private->Udp6ReadChild\r
326 );\r
327 }\r
328\r
329 if (Private->Mtftp6Child != NULL) {\r
330 //\r
331 // Close Mtftp6 for PxeBc->Mtftp and destroy the instance.\r
332 //\r
333 gBS->CloseProtocol (\r
334 Private->Mtftp6Child,\r
335 &gEfiMtftp6ProtocolGuid,\r
336 This->DriverBindingHandle,\r
337 Private->Controller\r
338 );\r
339\r
340 NetLibDestroyServiceChild (\r
341 Private->Controller,\r
342 This->DriverBindingHandle,\r
343 &gEfiMtftp6ServiceBindingProtocolGuid,\r
344 Private->Mtftp6Child\r
345 );\r
346 }\r
347\r
348 if (Private->Dhcp6Child != NULL) {\r
349 //\r
350 // Close Dhcp6 for PxeBc->Dhcp and destroy the instance.\r
351 //\r
352 gBS->CloseProtocol (\r
353 Private->Dhcp6Child,\r
354 &gEfiDhcp6ProtocolGuid,\r
355 This->DriverBindingHandle,\r
356 Private->Controller\r
357 );\r
358\r
359 NetLibDestroyServiceChild (\r
360 Private->Controller,\r
361 This->DriverBindingHandle,\r
362 &gEfiDhcp6ServiceBindingProtocolGuid,\r
363 Private->Dhcp6Child\r
364 );\r
365 }\r
366\r
367 if (Private->Ip6Nic != NULL) {\r
368 //\r
369 // Close PxeBc from the parent Nic handle and destroy the virtual handle.\r
370 //\r
371 gBS->CloseProtocol (\r
372 Private->Controller,\r
373 &gEfiPxeBaseCodeProtocolGuid,\r
374 This->DriverBindingHandle,\r
375 Private->Ip6Nic->Controller\r
376 );\r
377 gBS->UninstallMultipleProtocolInterfaces (\r
378 Private->Ip6Nic->Controller,\r
379 &gEfiDevicePathProtocolGuid,\r
380 Private->Ip6Nic->DevicePath,\r
381 &gEfiLoadFileProtocolGuid,\r
382 &Private->Ip6Nic->LoadFile,\r
383 NULL\r
384 );\r
385 FreePool (Private->Ip6Nic);\r
386 }\r
387\r
388 Private->Ip6Child = NULL;\r
389 Private->Udp6WriteChild = NULL;\r
390 Private->Udp6ReadChild = NULL;\r
391 Private->Mtftp6Child = NULL;\r
392 Private->Dhcp6Child = NULL;\r
393 Private->Ip6Nic = NULL;\r
394 Private->Mode.Ipv6Available = FALSE;\r
395}\r
396\r
397\r
398/**\r
399 Create the opened instances based on IPv4.\r
400\r
401 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.\r
402 @param[in] ControllerHandle Handle of the child to destroy.\r
403 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.\r
404\r
405 @retval EFI_SUCCESS The instances based on IPv4 were all created successfully.\r
406 @retval Others An unexpected error occurred.\r
407\r
408**/\r
409EFI_STATUS\r
410PxeBcCreateIp4Children (\r
411 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
412 IN EFI_HANDLE ControllerHandle,\r
413 IN PXEBC_PRIVATE_DATA *Private\r
414 )\r
415{\r
416 EFI_STATUS Status;\r
417 IPv4_DEVICE_PATH Ip4Node;\r
418 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;\r
419 EFI_PXE_BASE_CODE_MODE *Mode;\r
420 EFI_UDP4_CONFIG_DATA *Udp4CfgData;\r
421 EFI_IP4_CONFIG_DATA *Ip4CfgData;\r
422 EFI_IP4_MODE_DATA Ip4ModeData;\r
423\r
424 if (Private->Ip4Nic != NULL) {\r
425 //\r
426 // Already created before.\r
427 //\r
428 return EFI_SUCCESS;\r
429 }\r
430\r
431 //\r
432 // Create Dhcp4 child and open Dhcp4 protocol for PxeBc->Dhcp.\r
433 //\r
434 Status = NetLibCreateServiceChild (\r
435 ControllerHandle,\r
436 This->DriverBindingHandle,\r
437 &gEfiDhcp4ServiceBindingProtocolGuid,\r
438 &Private->Dhcp4Child\r
439 );\r
440 if (EFI_ERROR (Status)) {\r
441 goto ON_ERROR;\r
442 }\r
443\r
444 Status = gBS->OpenProtocol (\r
445 Private->Dhcp4Child,\r
446 &gEfiDhcp4ProtocolGuid,\r
447 (VOID **) &Private->Dhcp4,\r
448 This->DriverBindingHandle,\r
449 ControllerHandle,\r
450 EFI_OPEN_PROTOCOL_BY_DRIVER\r
451 );\r
452 if (EFI_ERROR (Status)) {\r
453 goto ON_ERROR;\r
454 }\r
455\r
456 //\r
457 // Create Mtftp4 child and open Mtftp4 protocol for PxeBc->Mtftp.\r
458 //\r
459 Status = NetLibCreateServiceChild (\r
460 ControllerHandle,\r
461 This->DriverBindingHandle,\r
462 &gEfiMtftp4ServiceBindingProtocolGuid,\r
463 &Private->Mtftp4Child\r
464 );\r
465 if (EFI_ERROR (Status)) {\r
466 goto ON_ERROR;\r
467 }\r
468\r
469 Status = gBS->OpenProtocol (\r
470 Private->Mtftp4Child,\r
471 &gEfiMtftp4ProtocolGuid,\r
472 (VOID **) &Private->Mtftp4,\r
473 This->DriverBindingHandle,\r
474 ControllerHandle,\r
475 EFI_OPEN_PROTOCOL_BY_DRIVER\r
476 );\r
477 if (EFI_ERROR (Status)) {\r
478 goto ON_ERROR;\r
479 }\r
480\r
481 //\r
482 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpRead.\r
483 //\r
484 Status = NetLibCreateServiceChild (\r
485 ControllerHandle,\r
486 This->DriverBindingHandle,\r
487 &gEfiUdp4ServiceBindingProtocolGuid,\r
488 &Private->Udp4ReadChild\r
489 );\r
490 if (EFI_ERROR (Status)) {\r
491 goto ON_ERROR;\r
492 }\r
493\r
494 Status = gBS->OpenProtocol (\r
495 Private->Udp4ReadChild,\r
496 &gEfiUdp4ProtocolGuid,\r
497 (VOID **) &Private->Udp4Read,\r
498 This->DriverBindingHandle,\r
499 ControllerHandle,\r
500 EFI_OPEN_PROTOCOL_BY_DRIVER\r
501 );\r
502 if (EFI_ERROR (Status)) {\r
503 goto ON_ERROR;\r
504 }\r
505\r
506 //\r
507 // Create Udp4 child and open Udp4 protocol for PxeBc->UdpWrite.\r
508 //\r
509 Status = NetLibCreateServiceChild (\r
510 ControllerHandle,\r
511 This->DriverBindingHandle,\r
512 &gEfiUdp4ServiceBindingProtocolGuid,\r
513 &Private->Udp4WriteChild\r
514 );\r
515 if (EFI_ERROR (Status)) {\r
516 goto ON_ERROR;\r
517 }\r
518\r
519 Status = gBS->OpenProtocol (\r
520 Private->Udp4WriteChild,\r
521 &gEfiUdp4ProtocolGuid,\r
522 (VOID **) &Private->Udp4Write,\r
523 This->DriverBindingHandle,\r
524 ControllerHandle,\r
525 EFI_OPEN_PROTOCOL_BY_DRIVER\r
526 );\r
527 if (EFI_ERROR (Status)) {\r
528 goto ON_ERROR;\r
529 }\r
530\r
531 //\r
532 // Create Arp child and open Arp protocol for PxeBc->Arp.\r
533 //\r
534 Status = NetLibCreateServiceChild (\r
535 ControllerHandle,\r
536 This->DriverBindingHandle,\r
537 &gEfiArpServiceBindingProtocolGuid,\r
538 &Private->ArpChild\r
539 );\r
540 if (EFI_ERROR (Status)) {\r
541 goto ON_ERROR;\r
542 }\r
543\r
544 Status = gBS->OpenProtocol (\r
545 Private->ArpChild,\r
546 &gEfiArpProtocolGuid,\r
547 (VOID **) &Private->Arp,\r
548 This->DriverBindingHandle,\r
549 ControllerHandle,\r
550 EFI_OPEN_PROTOCOL_BY_DRIVER\r
551 );\r
552 if (EFI_ERROR (Status)) {\r
553 goto ON_ERROR;\r
554 }\r
555\r
556 //\r
557 // Create Ip4 child and open Ip4 protocol for background ICMP packets.\r
558 //\r
559 Status = NetLibCreateServiceChild (\r
560 ControllerHandle,\r
561 This->DriverBindingHandle,\r
562 &gEfiIp4ServiceBindingProtocolGuid,\r
563 &Private->Ip4Child\r
564 );\r
565 if (EFI_ERROR (Status)) {\r
566 goto ON_ERROR;\r
567 }\r
568\r
569 Status = gBS->OpenProtocol (\r
570 Private->Ip4Child,\r
571 &gEfiIp4ProtocolGuid,\r
572 (VOID **) &Private->Ip4,\r
573 This->DriverBindingHandle,\r
574 ControllerHandle,\r
575 EFI_OPEN_PROTOCOL_BY_DRIVER\r
576 );\r
577 if (EFI_ERROR (Status)) {\r
578 goto ON_ERROR;\r
579 }\r
580\r
581 //\r
582 // Get max packet size from Ip4 to calculate block size for Tftp later.\r
583 //\r
584 Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);\r
585 if (EFI_ERROR (Status)) {\r
586 goto ON_ERROR;\r
587 }\r
588\r
589 Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;\r
590\r
591 Private->Ip4Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));\r
592 if (Private->Ip4Nic == NULL) {\r
593 return EFI_OUT_OF_RESOURCES;\r
594 }\r
595\r
596 Private->Ip4Nic->Private = Private;\r
597 Private->Ip4Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;\r
598\r
599 //\r
600 // Create a device path node for Ipv4 virtual nic, and append it.\r
601 //\r
602 ZeroMem (&Ip4Node, sizeof (IPv4_DEVICE_PATH));\r
603 Ip4Node.Header.Type = MESSAGING_DEVICE_PATH;\r
604 Ip4Node.Header.SubType = MSG_IPv4_DP;\r
605 Ip4Node.StaticIpAddress = FALSE;\r
606\r
607 SetDevicePathNodeLength (&Ip4Node.Header, sizeof (Ip4Node));\r
608\r
609 Private->Ip4Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip4Node.Header);\r
610\r
611 if (Private->Ip4Nic->DevicePath == NULL) {\r
612 Status = EFI_OUT_OF_RESOURCES;\r
613 goto ON_ERROR;\r
614 }\r
615\r
616 CopyMem (\r
617 &Private->Ip4Nic->LoadFile,\r
618 &gLoadFileProtocolTemplate,\r
619 sizeof (EFI_LOAD_FILE_PROTOCOL)\r
620 );\r
621\r
622 //\r
623 // Create a new handle for IPv4 virtual nic,\r
624 // and install PxeBaseCode, LoadFile and DevicePath protocols.\r
625 //\r
626 Status = gBS->InstallMultipleProtocolInterfaces (\r
627 &Private->Ip4Nic->Controller,\r
628 &gEfiDevicePathProtocolGuid,\r
629 Private->Ip4Nic->DevicePath,\r
630 &gEfiLoadFileProtocolGuid,\r
631 &Private->Ip4Nic->LoadFile,\r
632 NULL\r
633 );\r
634 if (EFI_ERROR (Status)) {\r
635 goto ON_ERROR;\r
636 }\r
637\r
638 //\r
639 // Open PxeBaseCode protocol by child to setup a parent-child relationship between\r
640 // real NIC handle and the virtual IPv4 NIC handle.\r
641 //\r
642 Status = gBS->OpenProtocol (\r
643 ControllerHandle,\r
644 &gEfiPxeBaseCodeProtocolGuid,\r
645 (VOID **) &PxeBc,\r
646 This->DriverBindingHandle,\r
647 Private->Ip4Nic->Controller,\r
648 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
649 );\r
650 if (EFI_ERROR (Status)) {\r
651 goto ON_ERROR;\r
652 }\r
653\r
654 //\r
655 // Set default configure data for Udp4Read and Ip4 instance.\r
656 //\r
657 Mode = PxeBc->Mode;\r
658 Udp4CfgData = &Private->Udp4CfgData;\r
659 Ip4CfgData = &Private->Ip4CfgData;\r
660\r
661 Udp4CfgData->AcceptBroadcast = TRUE;\r
662 Udp4CfgData->AcceptAnyPort = TRUE;\r
663 Udp4CfgData->AllowDuplicatePort = TRUE;\r
664 Udp4CfgData->TypeOfService = Mode->ToS;\r
665 Udp4CfgData->TimeToLive = Mode->TTL;\r
666 Udp4CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;\r
667 Udp4CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;\r
668\r
669 Ip4CfgData->AcceptIcmpErrors = TRUE;\r
670 Ip4CfgData->DefaultProtocol = EFI_IP_PROTO_ICMP;\r
671 Ip4CfgData->TypeOfService = Mode->ToS;\r
672 Ip4CfgData->TimeToLive = Mode->TTL;\r
673 Ip4CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;\r
674 Ip4CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;\r
675\r
676 return EFI_SUCCESS;\r
677\r
678ON_ERROR:\r
679 PxeBcDestroyIp4Children (This, Private);\r
680 return Status;\r
681}\r
682\r
683\r
684/**\r
685 Create the opened instances based on IPv6.\r
686\r
687 @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL.\r
688 @param[in] ControllerHandle Handle of the child to destroy.\r
689 @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA.\r
690\r
691 @retval EFI_SUCCESS The instances based on IPv6 were all created successfully.\r
692 @retval Others An unexpected error occurred.\r
693\r
694**/\r
695EFI_STATUS\r
696PxeBcCreateIp6Children (\r
697 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
698 IN EFI_HANDLE ControllerHandle,\r
699 IN PXEBC_PRIVATE_DATA *Private\r
700 )\r
701{\r
702 EFI_STATUS Status;\r
703 IPv6_DEVICE_PATH Ip6Node;\r
704 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;\r
705 EFI_UDP6_CONFIG_DATA *Udp6CfgData;\r
706 EFI_IP6_CONFIG_DATA *Ip6CfgData;\r
707 EFI_IP6_MODE_DATA Ip6ModeData;\r
708\r
709 if (Private->Ip6Nic != NULL) {\r
710 //\r
711 // Already created before.\r
712 //\r
713 return EFI_SUCCESS;\r
714 }\r
715\r
716 Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));\r
717\r
718 if (Private->Ip6Nic == NULL) {\r
719 return EFI_OUT_OF_RESOURCES;\r
720 }\r
721\r
722 Private->Ip6Nic->Private = Private;\r
723 Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;\r
724\r
725 //\r
726 // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.\r
727 //\r
728 Status = NetLibCreateServiceChild (\r
729 ControllerHandle,\r
730 This->DriverBindingHandle,\r
731 &gEfiDhcp6ServiceBindingProtocolGuid,\r
732 &Private->Dhcp6Child\r
733 );\r
734 if (EFI_ERROR (Status)) {\r
735 goto ON_ERROR;\r
736 }\r
737\r
738 Status = gBS->OpenProtocol (\r
739 Private->Dhcp6Child,\r
740 &gEfiDhcp6ProtocolGuid,\r
741 (VOID **) &Private->Dhcp6,\r
742 This->DriverBindingHandle,\r
743 ControllerHandle,\r
744 EFI_OPEN_PROTOCOL_BY_DRIVER\r
745 );\r
746 if (EFI_ERROR (Status)) {\r
747 goto ON_ERROR;\r
748 }\r
749\r
750 //\r
751 // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.\r
752 //\r
753 Status = NetLibCreateServiceChild (\r
754 ControllerHandle,\r
755 This->DriverBindingHandle,\r
756 &gEfiMtftp6ServiceBindingProtocolGuid,\r
757 &Private->Mtftp6Child\r
758 );\r
759 if (EFI_ERROR (Status)) {\r
760 goto ON_ERROR;\r
761 }\r
762\r
763 Status = gBS->OpenProtocol (\r
764 Private->Mtftp6Child,\r
765 &gEfiMtftp6ProtocolGuid,\r
766 (VOID **) &Private->Mtftp6,\r
767 This->DriverBindingHandle,\r
768 ControllerHandle,\r
769 EFI_OPEN_PROTOCOL_BY_DRIVER\r
770 );\r
771 if (EFI_ERROR (Status)) {\r
772 goto ON_ERROR;\r
773 }\r
774\r
775 //\r
776 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.\r
777 //\r
778 Status = NetLibCreateServiceChild (\r
779 ControllerHandle,\r
780 This->DriverBindingHandle,\r
781 &gEfiUdp6ServiceBindingProtocolGuid,\r
782 &Private->Udp6ReadChild\r
783 );\r
784 if (EFI_ERROR (Status)) {\r
785 goto ON_ERROR;\r
786 }\r
787\r
788 Status = gBS->OpenProtocol (\r
789 Private->Udp6ReadChild,\r
790 &gEfiUdp6ProtocolGuid,\r
791 (VOID **) &Private->Udp6Read,\r
792 This->DriverBindingHandle,\r
793 ControllerHandle,\r
794 EFI_OPEN_PROTOCOL_BY_DRIVER\r
795 );\r
796 if (EFI_ERROR (Status)) {\r
797 goto ON_ERROR;\r
798 }\r
799\r
800 //\r
801 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.\r
802 //\r
803 Status = NetLibCreateServiceChild (\r
804 ControllerHandle,\r
805 This->DriverBindingHandle,\r
806 &gEfiUdp6ServiceBindingProtocolGuid,\r
807 &Private->Udp6WriteChild\r
808 );\r
809 if (EFI_ERROR (Status)) {\r
810 goto ON_ERROR;\r
811 }\r
812\r
813 Status = gBS->OpenProtocol (\r
814 Private->Udp6WriteChild,\r
815 &gEfiUdp6ProtocolGuid,\r
816 (VOID **) &Private->Udp6Write,\r
817 This->DriverBindingHandle,\r
818 ControllerHandle,\r
819 EFI_OPEN_PROTOCOL_BY_DRIVER\r
820 );\r
821 if (EFI_ERROR (Status)) {\r
822 goto ON_ERROR;\r
823 }\r
824\r
825 //\r
826 // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.\r
827 //\r
828 Status = NetLibCreateServiceChild (\r
829 ControllerHandle,\r
830 This->DriverBindingHandle,\r
831 &gEfiIp6ServiceBindingProtocolGuid,\r
832 &Private->Ip6Child\r
833 );\r
834 if (EFI_ERROR (Status)) {\r
835 goto ON_ERROR;\r
836 }\r
837\r
838 Status = gBS->OpenProtocol (\r
839 Private->Ip6Child,\r
840 &gEfiIp6ProtocolGuid,\r
841 (VOID **) &Private->Ip6,\r
842 This->DriverBindingHandle,\r
843 ControllerHandle,\r
844 EFI_OPEN_PROTOCOL_BY_DRIVER\r
845 );\r
846 if (EFI_ERROR (Status)) {\r
847 goto ON_ERROR;\r
848 }\r
849\r
850 //\r
851 // Get max packet size from Ip6 to calculate block size for Tftp later.\r
852 //\r
853 Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL);\r
854 if (EFI_ERROR (Status)) {\r
855 goto ON_ERROR;\r
856 }\r
857\r
858 Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;\r
859\r
860 //\r
861 // Locate Ip6->Ip6Config and store it for set IPv6 address.\r
862 //\r
863 Status = gBS->HandleProtocol (\r
864 ControllerHandle,\r
865 &gEfiIp6ConfigProtocolGuid,\r
866 (VOID **) &Private->Ip6Cfg\r
867 );\r
868 if (EFI_ERROR (Status)) {\r
869 goto ON_ERROR;\r
870 }\r
871\r
872 //\r
873 // Create a device path node for Ipv6 virtual nic, and append it.\r
874 //\r
875 ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));\r
876 Ip6Node.Header.Type = MESSAGING_DEVICE_PATH;\r
877 Ip6Node.Header.SubType = MSG_IPv6_DP;\r
878 Ip6Node.StaticIpAddress = FALSE;\r
879\r
880 SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));\r
881\r
882 Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);\r
883\r
884 if (Private->Ip6Nic->DevicePath == NULL) {\r
885 Status = EFI_OUT_OF_RESOURCES;\r
886 goto ON_ERROR;\r
887 }\r
888\r
889 CopyMem (\r
890 &Private->Ip6Nic->LoadFile,\r
891 &gLoadFileProtocolTemplate,\r
892 sizeof (EFI_LOAD_FILE_PROTOCOL)\r
893 );\r
894\r
895 //\r
896 // Create a new handle for IPv6 virtual nic,\r
897 // and install PxeBaseCode, LoadFile and DevicePath protocols.\r
898 //\r
899 Status = gBS->InstallMultipleProtocolInterfaces (\r
900 &Private->Ip6Nic->Controller,\r
901 &gEfiDevicePathProtocolGuid,\r
902 Private->Ip6Nic->DevicePath,\r
903 &gEfiLoadFileProtocolGuid,\r
904 &Private->Ip6Nic->LoadFile,\r
905 NULL\r
906 );\r
907 if (EFI_ERROR (Status)) {\r
908 goto ON_ERROR;\r
909 }\r
910\r
911 //\r
912 // Open PxeBaseCode protocol by child to setup a parent-child relationship between\r
913 // real NIC handle and the virtual IPv6 NIC handle.\r
914 //\r
915 Status = gBS->OpenProtocol (\r
916 ControllerHandle,\r
917 &gEfiPxeBaseCodeProtocolGuid,\r
918 (VOID **) &PxeBc,\r
919 This->DriverBindingHandle,\r
920 Private->Ip6Nic->Controller,\r
921 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
922 );\r
923 if (EFI_ERROR (Status)) {\r
924 goto ON_ERROR;\r
925 }\r
926\r
927 //\r
928 // Set IPv6 avaiable flag and set default configure data for\r
929 // Udp6Read and Ip6 instance.\r
930 //\r
931 Private->Mode.Ipv6Available = TRUE;\r
932 Udp6CfgData = &Private->Udp6CfgData;\r
933 Ip6CfgData = &Private->Ip6CfgData;\r
934\r
935 Udp6CfgData->AcceptAnyPort = TRUE;\r
936 Udp6CfgData->AllowDuplicatePort = TRUE;\r
937 Udp6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT;\r
938 Udp6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;\r
939 Udp6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;\r
940\r
941 Ip6CfgData->AcceptIcmpErrors = TRUE;\r
942 Ip6CfgData->DefaultProtocol = IP6_ICMP;\r
943 Ip6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT;\r
944 Ip6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;\r
945 Ip6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;\r
946\r
947 return EFI_SUCCESS;\r
948\r
949ON_ERROR:\r
950 PxeBcDestroyIp6Children (This, Private);\r
951 return Status;\r
952}\r
953\r
954\r
955/**\r
956 The entry point for UefiPxeBc driver that installs the driver\r
957 binding and component name protocol on its image.\r
958\r
959 @param[in] ImageHandle The Image handle of the driver.\r
960 @param[in] SystemTable The system table.\r
961\r
962 @return EFI_SUCCESS\r
963 @return Others\r
964\r
965**/\r
966EFI_STATUS\r
967EFIAPI\r
968PxeBcDriverEntryPoint (\r
969 IN EFI_HANDLE ImageHandle,\r
970 IN EFI_SYSTEM_TABLE *SystemTable\r
971 )\r
972{\r
973 return EfiLibInstallDriverBindingComponentName2 (\r
974 ImageHandle,\r
975 SystemTable,\r
976 &gPxeBcDriverBinding,\r
977 ImageHandle,\r
978 &gPxeBcComponentName,\r
979 &gPxeBcComponentName2\r
980 );\r
981}\r
982\r
983\r
984/**\r
985 Test to see if this driver supports ControllerHandle. This service\r
986 is called by the EFI boot service ConnectController(). In\r
987 order to make drivers as small as possible, there are a few calling\r
988 restrictions for this service. ConnectController() must\r
989 follow these calling restrictions. If any other agent wishes to call\r
990 Supported() it must also follow these calling restrictions.\r
991\r
992 @param[in] This The pointer to the driver binding protocol.\r
993 @param[in] ControllerHandle The handle of device to be tested.\r
994 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
995 device to be started.\r
996\r
997 @retval EFI_SUCCESS This driver supports this device.\r
998 @retval EFI_UNSUPPORTED This driver does not support this device.\r
999\r
1000**/\r
1001EFI_STATUS\r
1002EFIAPI\r
1003PxeBcDriverBindingSupported (\r
1004 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1005 IN EFI_HANDLE ControllerHandle,\r
1006 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1007 )\r
1008{\r
1009 EFI_STATUS Ip4Status;\r
1010 EFI_STATUS Ip6Status;\r
1011\r
1012 //\r
1013 // Try to open the Mtftp4 and Dhcp4 protocol to test whether IPv4 stack is ready.\r
1014 //\r
1015 Ip4Status = gBS->OpenProtocol (\r
1016 ControllerHandle,\r
1017 &gEfiDhcp4ServiceBindingProtocolGuid,\r
1018 NULL,\r
1019 This->DriverBindingHandle,\r
1020 ControllerHandle,\r
1021 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1022 );\r
1023 if (!EFI_ERROR (Ip4Status)) {\r
1024 Ip4Status = gBS->OpenProtocol (\r
1025 ControllerHandle,\r
1026 &gEfiMtftp4ServiceBindingProtocolGuid,\r
1027 NULL,\r
1028 This->DriverBindingHandle,\r
1029 ControllerHandle,\r
1030 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1031 );\r
1032 }\r
1033\r
1034 //\r
1035 // Try to open the Mtftp6 and Dhcp6 protocol to test whether IPv4 stack is ready.\r
1036 //\r
1037 Ip6Status = gBS->OpenProtocol (\r
1038 ControllerHandle,\r
1039 &gEfiDhcp6ServiceBindingProtocolGuid,\r
1040 NULL,\r
1041 This->DriverBindingHandle,\r
1042 ControllerHandle,\r
1043 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1044 );\r
1045 if (!EFI_ERROR (Ip6Status)) {\r
1046 Ip6Status = gBS->OpenProtocol (\r
1047 ControllerHandle,\r
1048 &gEfiMtftp6ServiceBindingProtocolGuid,\r
1049 NULL,\r
1050 This->DriverBindingHandle,\r
1051 ControllerHandle,\r
1052 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1053 );\r
1054 }\r
1055\r
1056 //\r
1057 // It's unsupported case if both stack are not ready.\r
1058 //\r
1059 if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {\r
1060 return EFI_UNSUPPORTED;\r
1061 }\r
1062\r
1063 return EFI_SUCCESS;\r
1064}\r
1065\r
1066\r
1067/**\r
1068 Start this driver on ControllerHandle. This service is called by the\r
1069 EFI boot service ConnectController(). In order to make\r
1070 drivers as small as possible, there are a few calling restrictions for\r
1071 this service. ConnectController() must follow these\r
1072 calling restrictions. If any other agent wishes to call Start() it\r
1073 must also follow these calling restrictions.\r
1074\r
1075 @param[in] This The pointer to the driver binding protocol.\r
1076 @param[in] ControllerHandle The handle of device to be started.\r
1077 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
1078 device to be started.\r
1079\r
1080 @retval EFI_SUCCESS This driver is installed to ControllerHandle.\r
1081 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
1082 @retval other This driver does not support this device.\r
1083\r
1084**/\r
1085EFI_STATUS\r
1086EFIAPI\r
1087PxeBcDriverBindingStart (\r
1088 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1089 IN EFI_HANDLE ControllerHandle,\r
1090 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1091 )\r
1092{\r
1093 PXEBC_PRIVATE_DATA *Private;\r
1094 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;\r
1095 EFI_STATUS Status;\r
1096 EFI_STATUS Ip4Status;\r
1097 EFI_STATUS Ip6Status;\r
1098\r
1099 Status = gBS->OpenProtocol (\r
1100 ControllerHandle,\r
1101 &gEfiPxeBaseCodeProtocolGuid,\r
1102 (VOID **) &PxeBc,\r
1103 This->DriverBindingHandle,\r
1104 ControllerHandle,\r
1105 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1106 );\r
1107 if (!EFI_ERROR (Status)) {\r
1108 //\r
1109 // Skip the initialization if the driver has been started already.\r
1110 //\r
1111 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);\r
1112 } else {\r
1113 //\r
1114 // If the driver has not been started yet, it should do initialization.\r
1115 //\r
1116 Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));\r
1117 if (Private == NULL) {\r
1118 return EFI_OUT_OF_RESOURCES;\r
1119 }\r
1120\r
1121 CopyMem (\r
1122 &Private->PxeBc,\r
1123 &gPxeBcProtocolTemplate,\r
1124 sizeof (EFI_PXE_BASE_CODE_PROTOCOL)\r
1125 );\r
1126\r
1127 Private->Signature = PXEBC_PRIVATE_DATA_SIGNATURE;\r
1128 Private->Controller = ControllerHandle;\r
1129 Private->Image = This->ImageHandle;\r
1130 Private->PxeBc.Mode = &Private->Mode;\r
1131 Private->Mode.Ipv6Supported = TRUE;\r
1132 Private->Mode.AutoArp = TRUE;\r
1133 Private->Mode.TTL = DEFAULT_TTL;\r
1134 Private->Mode.ToS = DEFAULT_ToS;\r
1135\r
1136 //\r
1137 // Open device path to prepare for appending virtual NIC node.\r
1138 //\r
1139 Status = gBS->OpenProtocol (\r
1140 ControllerHandle,\r
1141 &gEfiDevicePathProtocolGuid,\r
1142 (VOID **) &Private->DevicePath,\r
1143 This->DriverBindingHandle,\r
1144 ControllerHandle,\r
1145 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1146 );\r
1147\r
1148 if (EFI_ERROR (Status)) {\r
1149 goto ON_ERROR;\r
1150 }\r
1151\r
1152 //\r
1153 // Get the NII interface if it exists, it's not required.\r
1154 //\r
1155 Status = gBS->OpenProtocol (\r
1156 ControllerHandle,\r
1157 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
1158 (VOID **) &Private->Nii,\r
1159 This->DriverBindingHandle,\r
1160 ControllerHandle,\r
1161 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1162 );\r
1163 if (EFI_ERROR (Status)) {\r
1164 Private->Nii = NULL;\r
1165 }\r
1166\r
1167 //\r
1168 // Install PxeBaseCode protocol onto the real NIC handler.\r
1169 //\r
1170 Status = gBS->InstallProtocolInterface (\r
1171 &ControllerHandle,\r
1172 &gEfiPxeBaseCodeProtocolGuid,\r
1173 EFI_NATIVE_INTERFACE,\r
1174 &Private->PxeBc\r
1175 );\r
1176 if (EFI_ERROR (Status)) {\r
1177 goto ON_ERROR;\r
1178 }\r
1179 }\r
1180\r
1181 //\r
1182 // Try to create virtual NIC handle for IPv4.\r
1183 //\r
1184 Ip4Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);\r
1185\r
1186 //\r
1187 // Try to create virtual NIC handle for IPv6.\r
1188 //\r
1189 Ip6Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);\r
1190\r
1191 if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {\r
1192 //\r
1193 // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.\r
1194 //\r
1195 Status = EFI_DEVICE_ERROR;\r
1196 goto ON_ERROR;\r
1197 }\r
1198\r
1199 return EFI_SUCCESS;\r
1200\r
1201ON_ERROR:\r
1202 gBS->UninstallProtocolInterface (\r
1203 ControllerHandle,\r
1204 &gEfiPxeBaseCodeProtocolGuid,\r
1205 &Private->PxeBc\r
1206 );\r
1207 PxeBcDestroyIp4Children (This, Private);\r
1208 PxeBcDestroyIp6Children (This, Private);\r
1209 FreePool (Private);\r
1210\r
1211 return Status;\r
1212}\r
1213\r
1214\r
1215/**\r
1216 Stop this driver on ControllerHandle. This service is called by the\r
1217 EFI boot service DisconnectController(). In order to\r
1218 make drivers as small as possible, there are a few calling\r
1219 restrictions for this service. DisconnectController()\r
1220 must follow these calling restrictions. If any other agent wishes\r
1221 to call Stop() it must also follow these calling restrictions.\r
1222\r
1223 @param[in] This Protocol instance pointer.\r
1224 @param[in] ControllerHandle Handle of device to stop driver on.\r
1225 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
1226 children is zero stop the entire bus driver.\r
1227 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
1228\r
1229 @retval EFI_SUCCESS This driver was removed ControllerHandle.\r
1230 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
1231 @retval Others This driver was not removed from this device\r
1232\r
1233**/\r
1234EFI_STATUS\r
1235EFIAPI\r
1236PxeBcDriverBindingStop (\r
1237 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1238 IN EFI_HANDLE ControllerHandle,\r
1239 IN UINTN NumberOfChildren,\r
1240 IN EFI_HANDLE *ChildHandleBuffer\r
1241 )\r
1242{\r
1243 PXEBC_PRIVATE_DATA *Private;\r
1244 PXEBC_VIRTUAL_NIC *VirtualNic;\r
1245 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;\r
1246 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
1247 EFI_STATUS Status;\r
1248 EFI_HANDLE NicHandle;\r
1249 BOOLEAN IsIpv6;\r
1250\r
1251 Private = NULL;\r
1252 NicHandle = NULL;\r
1253 VirtualNic = NULL;\r
1254 LoadFile = NULL;\r
1255 PxeBc = NULL;\r
1256 IsIpv6 = FALSE;\r
1257\r
1258 Status = gBS->OpenProtocol (\r
1259 ControllerHandle,\r
1260 &gEfiLoadFileProtocolGuid,\r
1261 (VOID **) &LoadFile,\r
1262 This->DriverBindingHandle,\r
1263 ControllerHandle,\r
1264 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1265 );\r
1266 if (EFI_ERROR (Status)) {\r
1267 //\r
1268 // Get the Nic handle by any pass-over service child handle.\r
1269 //\r
1270 NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);\r
1271 if (NicHandle == NULL) {\r
1272 NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);\r
1273 if (NicHandle == NULL) {\r
1274 return EFI_DEVICE_ERROR;\r
1275 } else {\r
1276 IsIpv6 = TRUE;\r
1277 }\r
1278 }\r
1279\r
1280 //\r
1281 // Try to retrieve the private data by PxeBc protocol.\r
1282 //\r
1283 Status = gBS->OpenProtocol (\r
1284 NicHandle,\r
1285 &gEfiPxeBaseCodeProtocolGuid,\r
1286 (VOID **) &PxeBc,\r
1287 This->DriverBindingHandle,\r
1288 ControllerHandle,\r
1289 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1290 );\r
1291 if (EFI_ERROR (Status)) {\r
1292 return Status;\r
1293 }\r
1294 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);\r
1295\r
1296 } else {\r
1297 //\r
1298 // It's a virtual handle with LoadFileProtocol.\r
1299 //\r
1300 Status = gBS->OpenProtocol (\r
1301 ControllerHandle,\r
1302 &gEfiLoadFileProtocolGuid,\r
1303 (VOID **) &LoadFile,\r
1304 This->DriverBindingHandle,\r
1305 ControllerHandle,\r
1306 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1307 );\r
1308 if (EFI_ERROR (Status)) {\r
1309 return Status;\r
1310 }\r
1311\r
1312 VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);\r
1313 Private = VirtualNic->Private;\r
1314 NicHandle = Private->Controller;\r
1315\r
1316 if (Private->Ip6Nic == VirtualNic) {\r
1317 IsIpv6 = TRUE;\r
1318 }\r
1319 }\r
1320\r
1321 if (Private->Ip4Nic != NULL && !IsIpv6) {\r
1322 PxeBcDestroyIp4Children (This, Private);\r
1323 }\r
1324\r
1325 if (Private->Ip6Nic != NULL && IsIpv6) {\r
1326 PxeBcDestroyIp6Children (This, Private);\r
1327 }\r
1328\r
1329 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
1330 gBS->UninstallProtocolInterface (\r
1331 NicHandle,\r
1332 &gEfiPxeBaseCodeProtocolGuid,\r
1333 &Private->PxeBc\r
1334 );\r
1335 FreePool (Private);\r
1336 }\r
1337\r
1338 return EFI_SUCCESS;\r
1339}\r