]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/UefiPxeBcDxe/PxeBcDriver.c
1. Fix a bug in PXE driver that the PXE boot do not restart if a new boot option...
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcDriver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 Driver Binding functions implementationfor for UefiPxeBc Driver.\r
3\r
75dce340 4 Copyright (c) 2007 - 2012, 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
75dce340 782 UINTN Index;\r
a3bcde70
HT
783\r
784 if (Private->Ip6Nic != NULL) {\r
785 //\r
786 // Already created before.\r
787 //\r
788 return EFI_SUCCESS;\r
789 }\r
790\r
791 Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC));\r
792\r
793 if (Private->Ip6Nic == NULL) {\r
794 return EFI_OUT_OF_RESOURCES;\r
795 }\r
796\r
797 Private->Ip6Nic->Private = Private;\r
798 Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE;\r
799\r
800 //\r
801 // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp.\r
802 //\r
803 Status = NetLibCreateServiceChild (\r
804 ControllerHandle,\r
805 This->DriverBindingHandle,\r
806 &gEfiDhcp6ServiceBindingProtocolGuid,\r
807 &Private->Dhcp6Child\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->Dhcp6Child,\r
815 &gEfiDhcp6ProtocolGuid,\r
816 (VOID **) &Private->Dhcp6,\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
75dce340 825 //\r
826 // Generate a random IAID for the Dhcp6 assigned address.\r
827 //\r
828 Private->IaId = NET_RANDOM (NetRandomInitSeed ());\r
829 if (Private->Snp != NULL) {\r
830 for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) {\r
831 Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31));\r
832 } \r
833 }\r
834\r
a3bcde70
HT
835 //\r
836 // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp.\r
837 //\r
838 Status = NetLibCreateServiceChild (\r
839 ControllerHandle,\r
840 This->DriverBindingHandle,\r
841 &gEfiMtftp6ServiceBindingProtocolGuid,\r
842 &Private->Mtftp6Child\r
843 );\r
844 if (EFI_ERROR (Status)) {\r
845 goto ON_ERROR;\r
846 }\r
847\r
848 Status = gBS->OpenProtocol (\r
849 Private->Mtftp6Child,\r
850 &gEfiMtftp6ProtocolGuid,\r
851 (VOID **) &Private->Mtftp6,\r
852 This->DriverBindingHandle,\r
853 ControllerHandle,\r
854 EFI_OPEN_PROTOCOL_BY_DRIVER\r
855 );\r
856 if (EFI_ERROR (Status)) {\r
857 goto ON_ERROR;\r
858 }\r
859\r
860 //\r
861 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead.\r
862 //\r
863 Status = NetLibCreateServiceChild (\r
864 ControllerHandle,\r
865 This->DriverBindingHandle,\r
866 &gEfiUdp6ServiceBindingProtocolGuid,\r
867 &Private->Udp6ReadChild\r
868 );\r
869 if (EFI_ERROR (Status)) {\r
870 goto ON_ERROR;\r
871 }\r
872\r
873 Status = gBS->OpenProtocol (\r
874 Private->Udp6ReadChild,\r
875 &gEfiUdp6ProtocolGuid,\r
876 (VOID **) &Private->Udp6Read,\r
877 This->DriverBindingHandle,\r
878 ControllerHandle,\r
879 EFI_OPEN_PROTOCOL_BY_DRIVER\r
880 );\r
881 if (EFI_ERROR (Status)) {\r
882 goto ON_ERROR;\r
883 }\r
884\r
885 //\r
886 // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite.\r
887 //\r
888 Status = NetLibCreateServiceChild (\r
889 ControllerHandle,\r
890 This->DriverBindingHandle,\r
891 &gEfiUdp6ServiceBindingProtocolGuid,\r
892 &Private->Udp6WriteChild\r
893 );\r
894 if (EFI_ERROR (Status)) {\r
895 goto ON_ERROR;\r
896 }\r
897\r
898 Status = gBS->OpenProtocol (\r
899 Private->Udp6WriteChild,\r
900 &gEfiUdp6ProtocolGuid,\r
901 (VOID **) &Private->Udp6Write,\r
902 This->DriverBindingHandle,\r
903 ControllerHandle,\r
904 EFI_OPEN_PROTOCOL_BY_DRIVER\r
905 );\r
906 if (EFI_ERROR (Status)) {\r
907 goto ON_ERROR;\r
908 }\r
909\r
910 //\r
911 // Create Ip6 child and open Ip6 protocol for background ICMP6 packets.\r
912 //\r
913 Status = NetLibCreateServiceChild (\r
914 ControllerHandle,\r
915 This->DriverBindingHandle,\r
916 &gEfiIp6ServiceBindingProtocolGuid,\r
917 &Private->Ip6Child\r
918 );\r
919 if (EFI_ERROR (Status)) {\r
920 goto ON_ERROR;\r
921 }\r
922\r
923 Status = gBS->OpenProtocol (\r
924 Private->Ip6Child,\r
925 &gEfiIp6ProtocolGuid,\r
926 (VOID **) &Private->Ip6,\r
927 This->DriverBindingHandle,\r
928 ControllerHandle,\r
929 EFI_OPEN_PROTOCOL_BY_DRIVER\r
930 );\r
931 if (EFI_ERROR (Status)) {\r
932 goto ON_ERROR;\r
933 }\r
934\r
935 //\r
936 // Get max packet size from Ip6 to calculate block size for Tftp later.\r
937 //\r
938 Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL);\r
939 if (EFI_ERROR (Status)) {\r
940 goto ON_ERROR;\r
941 }\r
942\r
943 Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize;\r
944\r
945 //\r
946 // Locate Ip6->Ip6Config and store it for set IPv6 address.\r
947 //\r
948 Status = gBS->HandleProtocol (\r
949 ControllerHandle,\r
950 &gEfiIp6ConfigProtocolGuid,\r
951 (VOID **) &Private->Ip6Cfg\r
952 );\r
953 if (EFI_ERROR (Status)) {\r
954 goto ON_ERROR;\r
955 }\r
956\r
957 //\r
958 // Create a device path node for Ipv6 virtual nic, and append it.\r
959 //\r
960 ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH));\r
961 Ip6Node.Header.Type = MESSAGING_DEVICE_PATH;\r
962 Ip6Node.Header.SubType = MSG_IPv6_DP;\r
501793fa 963 Ip6Node.PrefixLength = IP6_PREFIX_LENGTH;\r
a3bcde70
HT
964\r
965 SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node));\r
966\r
967 Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header);\r
968\r
969 if (Private->Ip6Nic->DevicePath == NULL) {\r
970 Status = EFI_OUT_OF_RESOURCES;\r
971 goto ON_ERROR;\r
972 }\r
973\r
974 CopyMem (\r
975 &Private->Ip6Nic->LoadFile,\r
976 &gLoadFileProtocolTemplate,\r
977 sizeof (EFI_LOAD_FILE_PROTOCOL)\r
978 );\r
979\r
980 //\r
981 // Create a new handle for IPv6 virtual nic,\r
982 // and install PxeBaseCode, LoadFile and DevicePath protocols.\r
983 //\r
984 Status = gBS->InstallMultipleProtocolInterfaces (\r
985 &Private->Ip6Nic->Controller,\r
986 &gEfiDevicePathProtocolGuid,\r
987 Private->Ip6Nic->DevicePath,\r
988 &gEfiLoadFileProtocolGuid,\r
989 &Private->Ip6Nic->LoadFile,\r
15f3fc85 990 &gEfiPxeBaseCodeProtocolGuid,\r
991 &Private->PxeBc,\r
a3bcde70
HT
992 NULL\r
993 );\r
994 if (EFI_ERROR (Status)) {\r
995 goto ON_ERROR;\r
996 }\r
15f3fc85 997 \r
998 if (Private->Snp != NULL) {\r
999 //\r
1000 // Install SNP protocol on purpose is for some OS loader backward\r
1001 // compatibility consideration.\r
1002 //\r
1003 Status = gBS->InstallProtocolInterface (\r
1004 &Private->Ip6Nic->Controller,\r
1005 &gEfiSimpleNetworkProtocolGuid,\r
1006 EFI_NATIVE_INTERFACE,\r
1007 Private->Snp\r
1008 );\r
1009 if (EFI_ERROR (Status)) {\r
1010 goto ON_ERROR;\r
1011 }\r
1012\r
1013 //\r
1014 // Open SNP on the child handle BY_DRIVER. It will prevent any additionally \r
1015 // layering to perform the experiment.\r
1016 //\r
1017 Status = gBS->OpenProtocol (\r
1018 Private->Ip6Nic->Controller,\r
1019 &gEfiSimpleNetworkProtocolGuid,\r
1020 (VOID **) &Snp,\r
1021 This->DriverBindingHandle,\r
1022 Private->Ip6Nic->Controller,\r
1023 EFI_OPEN_PROTOCOL_BY_DRIVER\r
1024 );\r
1025 if (EFI_ERROR (Status)) {\r
1026 goto ON_ERROR;\r
1027 }\r
1028 }\r
a3bcde70
HT
1029\r
1030 //\r
15f3fc85 1031 // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between\r
a3bcde70
HT
1032 // real NIC handle and the virtual IPv6 NIC handle.\r
1033 //\r
1034 Status = gBS->OpenProtocol (\r
1035 ControllerHandle,\r
9bdc6592 1036 &gEfiCallerIdGuid,\r
15f3fc85 1037 (VOID **) &Id,\r
a3bcde70
HT
1038 This->DriverBindingHandle,\r
1039 Private->Ip6Nic->Controller,\r
1040 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
1041 );\r
1042 if (EFI_ERROR (Status)) {\r
1043 goto ON_ERROR;\r
1044 }\r
1045\r
1046 //\r
1047 // Set IPv6 avaiable flag and set default configure data for\r
1048 // Udp6Read and Ip6 instance.\r
1049 //\r
1050 Private->Mode.Ipv6Available = TRUE;\r
1051 Udp6CfgData = &Private->Udp6CfgData;\r
1052 Ip6CfgData = &Private->Ip6CfgData;\r
1053\r
1054 Udp6CfgData->AcceptAnyPort = TRUE;\r
1055 Udp6CfgData->AllowDuplicatePort = TRUE;\r
1056 Udp6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT;\r
1057 Udp6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;\r
1058 Udp6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;\r
1059\r
1060 Ip6CfgData->AcceptIcmpErrors = TRUE;\r
1061 Ip6CfgData->DefaultProtocol = IP6_ICMP;\r
1062 Ip6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT;\r
1063 Ip6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;\r
1064 Ip6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME;\r
1065\r
1066 return EFI_SUCCESS;\r
1067\r
1068ON_ERROR:\r
1069 PxeBcDestroyIp6Children (This, Private);\r
1070 return Status;\r
1071}\r
1072\r
1073\r
1074/**\r
1075 The entry point for UefiPxeBc driver that installs the driver\r
1076 binding and component name protocol on its image.\r
1077\r
1078 @param[in] ImageHandle The Image handle of the driver.\r
1079 @param[in] SystemTable The system table.\r
1080\r
1081 @return EFI_SUCCESS\r
1082 @return Others\r
1083\r
1084**/\r
1085EFI_STATUS\r
1086EFIAPI\r
1087PxeBcDriverEntryPoint (\r
1088 IN EFI_HANDLE ImageHandle,\r
1089 IN EFI_SYSTEM_TABLE *SystemTable\r
1090 )\r
1091{\r
1092 return EfiLibInstallDriverBindingComponentName2 (\r
1093 ImageHandle,\r
1094 SystemTable,\r
1095 &gPxeBcDriverBinding,\r
1096 ImageHandle,\r
1097 &gPxeBcComponentName,\r
1098 &gPxeBcComponentName2\r
1099 );\r
1100}\r
1101\r
1102\r
1103/**\r
1104 Test to see if this driver supports ControllerHandle. This service\r
1105 is called by the EFI boot service ConnectController(). In\r
1106 order to make drivers as small as possible, there are a few calling\r
1107 restrictions for this service. ConnectController() must\r
1108 follow these calling restrictions. If any other agent wishes to call\r
1109 Supported() it must also follow these calling restrictions.\r
1110\r
1111 @param[in] This The pointer to the driver binding protocol.\r
1112 @param[in] ControllerHandle The handle of device to be tested.\r
1113 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
1114 device to be started.\r
1115\r
1116 @retval EFI_SUCCESS This driver supports this device.\r
1117 @retval EFI_UNSUPPORTED This driver does not support this device.\r
1118\r
1119**/\r
1120EFI_STATUS\r
1121EFIAPI\r
1122PxeBcDriverBindingSupported (\r
1123 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1124 IN EFI_HANDLE ControllerHandle,\r
1125 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1126 )\r
1127{\r
1128 EFI_STATUS Ip4Status;\r
1129 EFI_STATUS Ip6Status;\r
1130\r
1131 //\r
1132 // Try to open the Mtftp4 and Dhcp4 protocol to test whether IPv4 stack is ready.\r
1133 //\r
1134 Ip4Status = gBS->OpenProtocol (\r
1135 ControllerHandle,\r
1136 &gEfiDhcp4ServiceBindingProtocolGuid,\r
1137 NULL,\r
1138 This->DriverBindingHandle,\r
1139 ControllerHandle,\r
1140 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1141 );\r
1142 if (!EFI_ERROR (Ip4Status)) {\r
1143 Ip4Status = gBS->OpenProtocol (\r
1144 ControllerHandle,\r
1145 &gEfiMtftp4ServiceBindingProtocolGuid,\r
1146 NULL,\r
1147 This->DriverBindingHandle,\r
1148 ControllerHandle,\r
1149 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1150 );\r
1151 }\r
1152\r
1153 //\r
1154 // Try to open the Mtftp6 and Dhcp6 protocol to test whether IPv4 stack is ready.\r
1155 //\r
1156 Ip6Status = gBS->OpenProtocol (\r
1157 ControllerHandle,\r
1158 &gEfiDhcp6ServiceBindingProtocolGuid,\r
1159 NULL,\r
1160 This->DriverBindingHandle,\r
1161 ControllerHandle,\r
1162 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1163 );\r
1164 if (!EFI_ERROR (Ip6Status)) {\r
1165 Ip6Status = gBS->OpenProtocol (\r
1166 ControllerHandle,\r
1167 &gEfiMtftp6ServiceBindingProtocolGuid,\r
1168 NULL,\r
1169 This->DriverBindingHandle,\r
1170 ControllerHandle,\r
1171 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
1172 );\r
1173 }\r
1174\r
1175 //\r
1176 // It's unsupported case if both stack are not ready.\r
1177 //\r
1178 if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {\r
1179 return EFI_UNSUPPORTED;\r
1180 }\r
1181\r
1182 return EFI_SUCCESS;\r
1183}\r
1184\r
1185\r
1186/**\r
1187 Start this driver on ControllerHandle. This service is called by the\r
1188 EFI boot service ConnectController(). In order to make\r
1189 drivers as small as possible, there are a few calling restrictions for\r
1190 this service. ConnectController() must follow these\r
1191 calling restrictions. If any other agent wishes to call Start() it\r
1192 must also follow these calling restrictions.\r
1193\r
1194 @param[in] This The pointer to the driver binding protocol.\r
1195 @param[in] ControllerHandle The handle of device to be started.\r
1196 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
1197 device to be started.\r
1198\r
1199 @retval EFI_SUCCESS This driver is installed to ControllerHandle.\r
1200 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
1201 @retval other This driver does not support this device.\r
1202\r
1203**/\r
1204EFI_STATUS\r
1205EFIAPI\r
1206PxeBcDriverBindingStart (\r
1207 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1208 IN EFI_HANDLE ControllerHandle,\r
1209 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
1210 )\r
1211{\r
1212 PXEBC_PRIVATE_DATA *Private;\r
a3bcde70
HT
1213 EFI_STATUS Status;\r
1214 EFI_STATUS Ip4Status;\r
1215 EFI_STATUS Ip6Status;\r
15f3fc85 1216 PXEBC_PRIVATE_PROTOCOL *Id;\r
a3bcde70
HT
1217\r
1218 Status = gBS->OpenProtocol (\r
1219 ControllerHandle,\r
9bdc6592 1220 &gEfiCallerIdGuid,\r
15f3fc85 1221 (VOID **) &Id,\r
a3bcde70
HT
1222 This->DriverBindingHandle,\r
1223 ControllerHandle,\r
1224 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1225 );\r
1226 if (!EFI_ERROR (Status)) {\r
1227 //\r
1228 // Skip the initialization if the driver has been started already.\r
1229 //\r
15f3fc85 1230 Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);\r
a3bcde70
HT
1231 } else {\r
1232 //\r
1233 // If the driver has not been started yet, it should do initialization.\r
1234 //\r
1235 Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));\r
1236 if (Private == NULL) {\r
1237 return EFI_OUT_OF_RESOURCES;\r
1238 }\r
1239\r
1240 CopyMem (\r
1241 &Private->PxeBc,\r
1242 &gPxeBcProtocolTemplate,\r
1243 sizeof (EFI_PXE_BASE_CODE_PROTOCOL)\r
1244 );\r
1245\r
1246 Private->Signature = PXEBC_PRIVATE_DATA_SIGNATURE;\r
1247 Private->Controller = ControllerHandle;\r
1248 Private->Image = This->ImageHandle;\r
1249 Private->PxeBc.Mode = &Private->Mode;\r
1250 Private->Mode.Ipv6Supported = TRUE;\r
1251 Private->Mode.AutoArp = TRUE;\r
1252 Private->Mode.TTL = DEFAULT_TTL;\r
1253 Private->Mode.ToS = DEFAULT_ToS;\r
1254\r
1255 //\r
1256 // Open device path to prepare for appending virtual NIC node.\r
1257 //\r
1258 Status = gBS->OpenProtocol (\r
1259 ControllerHandle,\r
1260 &gEfiDevicePathProtocolGuid,\r
1261 (VOID **) &Private->DevicePath,\r
1262 This->DriverBindingHandle,\r
1263 ControllerHandle,\r
1264 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1265 );\r
1266\r
1267 if (EFI_ERROR (Status)) {\r
1268 goto ON_ERROR;\r
1269 }\r
1270\r
1271 //\r
1272 // Get the NII interface if it exists, it's not required.\r
1273 //\r
1274 Status = gBS->OpenProtocol (\r
1275 ControllerHandle,\r
1276 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
1277 (VOID **) &Private->Nii,\r
1278 This->DriverBindingHandle,\r
1279 ControllerHandle,\r
1280 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1281 );\r
1282 if (EFI_ERROR (Status)) {\r
1283 Private->Nii = NULL;\r
1284 }\r
1285\r
1286 //\r
15f3fc85 1287 // Install PxeBaseCodePrivate protocol onto the real NIC handler.\r
9bdc6592
LG
1288 // PxeBaseCodePrivate protocol is only used to keep the relationship between \r
1289 // NIC handle and virtual child handles.\r
1290 // gEfiCallerIdGuid will be used as its protocol guid.\r
a3bcde70
HT
1291 //\r
1292 Status = gBS->InstallProtocolInterface (\r
1293 &ControllerHandle,\r
9bdc6592 1294 &gEfiCallerIdGuid,\r
a3bcde70 1295 EFI_NATIVE_INTERFACE,\r
15f3fc85 1296 &Private->Id\r
a3bcde70
HT
1297 );\r
1298 if (EFI_ERROR (Status)) {\r
1299 goto ON_ERROR;\r
1300 }\r
15f3fc85 1301\r
1302 //\r
1303 // Try to locate SNP protocol.\r
1304 //\r
1305 NetLibGetSnpHandle(ControllerHandle, &Private->Snp); \r
a3bcde70
HT
1306 }\r
1307\r
1308 //\r
1309 // Try to create virtual NIC handle for IPv4.\r
1310 //\r
1311 Ip4Status = PxeBcCreateIp4Children (This, ControllerHandle, Private);\r
1312\r
1313 //\r
1314 // Try to create virtual NIC handle for IPv6.\r
1315 //\r
1316 Ip6Status = PxeBcCreateIp6Children (This, ControllerHandle, Private);\r
1317\r
1318 if (EFI_ERROR (Ip4Status) && EFI_ERROR (Ip6Status)) {\r
1319 //\r
1320 // Failed to start PXE driver if IPv4 and IPv6 stack are both not available.\r
1321 //\r
1322 Status = EFI_DEVICE_ERROR;\r
1323 goto ON_ERROR;\r
1324 }\r
1325\r
1326 return EFI_SUCCESS;\r
1327\r
1328ON_ERROR:\r
1329 gBS->UninstallProtocolInterface (\r
1330 ControllerHandle,\r
9bdc6592 1331 &gEfiCallerIdGuid,\r
15f3fc85 1332 &Private->Id\r
a3bcde70
HT
1333 );\r
1334 PxeBcDestroyIp4Children (This, Private);\r
1335 PxeBcDestroyIp6Children (This, Private);\r
1336 FreePool (Private);\r
1337\r
1338 return Status;\r
1339}\r
1340\r
1341\r
1342/**\r
1343 Stop this driver on ControllerHandle. This service is called by the\r
1344 EFI boot service DisconnectController(). In order to\r
1345 make drivers as small as possible, there are a few calling\r
1346 restrictions for this service. DisconnectController()\r
1347 must follow these calling restrictions. If any other agent wishes\r
1348 to call Stop() it must also follow these calling restrictions.\r
1349\r
1350 @param[in] This Protocol instance pointer.\r
1351 @param[in] ControllerHandle Handle of device to stop driver on.\r
1352 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
1353 children is zero stop the entire bus driver.\r
1354 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
1355\r
1356 @retval EFI_SUCCESS This driver was removed ControllerHandle.\r
1357 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
1358 @retval Others This driver was not removed from this device\r
1359\r
1360**/\r
1361EFI_STATUS\r
1362EFIAPI\r
1363PxeBcDriverBindingStop (\r
1364 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
1365 IN EFI_HANDLE ControllerHandle,\r
1366 IN UINTN NumberOfChildren,\r
1367 IN EFI_HANDLE *ChildHandleBuffer\r
1368 )\r
1369{\r
1370 PXEBC_PRIVATE_DATA *Private;\r
1371 PXEBC_VIRTUAL_NIC *VirtualNic;\r
a3bcde70
HT
1372 EFI_LOAD_FILE_PROTOCOL *LoadFile;\r
1373 EFI_STATUS Status;\r
1374 EFI_HANDLE NicHandle;\r
1375 BOOLEAN IsIpv6;\r
15f3fc85 1376 PXEBC_PRIVATE_PROTOCOL *Id;\r
a3bcde70
HT
1377\r
1378 Private = NULL;\r
1379 NicHandle = NULL;\r
1380 VirtualNic = NULL;\r
1381 LoadFile = NULL;\r
15f3fc85 1382 Id = NULL;\r
a3bcde70
HT
1383 IsIpv6 = FALSE;\r
1384\r
1385 Status = gBS->OpenProtocol (\r
1386 ControllerHandle,\r
1387 &gEfiLoadFileProtocolGuid,\r
1388 (VOID **) &LoadFile,\r
1389 This->DriverBindingHandle,\r
1390 ControllerHandle,\r
1391 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1392 );\r
1393 if (EFI_ERROR (Status)) {\r
1394 //\r
1395 // Get the Nic handle by any pass-over service child handle.\r
1396 //\r
1397 NicHandle = PxeBcGetNicByIp4Children (ControllerHandle);\r
1398 if (NicHandle == NULL) {\r
1399 NicHandle = PxeBcGetNicByIp6Children (ControllerHandle);\r
1400 if (NicHandle == NULL) {\r
1401 return EFI_DEVICE_ERROR;\r
1402 } else {\r
1403 IsIpv6 = TRUE;\r
1404 }\r
1405 }\r
1406\r
1407 //\r
15f3fc85 1408 // Try to retrieve the private data by PxeBcPrivate protocol.\r
a3bcde70
HT
1409 //\r
1410 Status = gBS->OpenProtocol (\r
1411 NicHandle,\r
9bdc6592 1412 &gEfiCallerIdGuid,\r
15f3fc85 1413 (VOID **) &Id,\r
a3bcde70
HT
1414 This->DriverBindingHandle,\r
1415 ControllerHandle,\r
1416 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1417 );\r
1418 if (EFI_ERROR (Status)) {\r
1419 return Status;\r
1420 }\r
15f3fc85 1421 Private = PXEBC_PRIVATE_DATA_FROM_ID (Id);\r
a3bcde70
HT
1422\r
1423 } else {\r
1424 //\r
1425 // It's a virtual handle with LoadFileProtocol.\r
1426 //\r
1427 Status = gBS->OpenProtocol (\r
1428 ControllerHandle,\r
1429 &gEfiLoadFileProtocolGuid,\r
1430 (VOID **) &LoadFile,\r
1431 This->DriverBindingHandle,\r
1432 ControllerHandle,\r
1433 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
1434 );\r
1435 if (EFI_ERROR (Status)) {\r
1436 return Status;\r
1437 }\r
1438\r
1439 VirtualNic = PXEBC_VIRTUAL_NIC_FROM_LOADFILE (LoadFile);\r
1440 Private = VirtualNic->Private;\r
1441 NicHandle = Private->Controller;\r
1442\r
1443 if (Private->Ip6Nic == VirtualNic) {\r
1444 IsIpv6 = TRUE;\r
1445 }\r
1446 }\r
1447\r
d6d78ac1 1448 //\r
1449 // Stop functionality of PXE Base Code protocol\r
1450 //\r
1451 Status = Private->PxeBc.Stop (&Private->PxeBc);\r
1452 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {\r
1453 return Status;\r
1454 }\r
1455\r
1456\r
a3bcde70
HT
1457 if (Private->Ip4Nic != NULL && !IsIpv6) {\r
1458 PxeBcDestroyIp4Children (This, Private);\r
1459 }\r
1460\r
1461 if (Private->Ip6Nic != NULL && IsIpv6) {\r
1462 PxeBcDestroyIp6Children (This, Private);\r
1463 }\r
1464\r
1465 if (Private->Ip4Nic == NULL && Private->Ip6Nic == NULL) {\r
1466 gBS->UninstallProtocolInterface (\r
1467 NicHandle,\r
9bdc6592 1468 &gEfiCallerIdGuid,\r
15f3fc85 1469 &Private->Id\r
a3bcde70
HT
1470 );\r
1471 FreePool (Private);\r
1472 }\r
1473\r
1474 return EFI_SUCCESS;\r
1475}\r