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