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