]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcDriver.c
Fix a bug for vlan ping failure.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / UefiPxeBcDxe / PxeBcDriver.c
1 /** @file
2 The driver binding for UEFI PXEBC protocol.
3
4 Copyright (c) 2007 - 2012, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15
16 #include "PxeBcImpl.h"
17
18 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {
19 PxeBcDriverBindingSupported,
20 PxeBcDriverBindingStart,
21 PxeBcDriverBindingStop,
22 0xa,
23 NULL,
24 NULL
25 };
26
27 /**
28 This is the declaration of an EFI image entry point. This entry point is
29 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
30 both device drivers and bus drivers.
31
32 @param ImageHandle The firmware allocated handle for the UEFI image.
33 @param SystemTable A pointer to the EFI System Table.
34
35 @retval EFI_SUCCESS The operation completed successfully.
36 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
37
38 **/
39 EFI_STATUS
40 EFIAPI
41 PxeBcDriverEntryPoint (
42 IN EFI_HANDLE ImageHandle,
43 IN EFI_SYSTEM_TABLE *SystemTable
44 )
45 {
46 return EfiLibInstallDriverBindingComponentName2 (
47 ImageHandle,
48 SystemTable,
49 &gPxeBcDriverBinding,
50 ImageHandle,
51 &gPxeBcComponentName,
52 &gPxeBcComponentName2
53 );
54 }
55
56
57 /**
58 Test to see if this driver supports ControllerHandle. This service
59 is called by the EFI boot service ConnectController(). In
60 order to make drivers as small as possible, there are a few calling
61 restrictions for this service. ConnectController() must
62 follow these calling restrictions. If any other agent wishes to call
63 Supported() it must also follow these calling restrictions.
64 PxeBc requires DHCP4 and MTFTP4 protocols.
65
66 @param This Protocol instance pointer.
67 @param ControllerHandle Handle of device to test
68 @param RemainingDevicePath Optional parameter use to pick a specific child
69 device to start.
70
71 @retval EFI_SUCCESS This driver supports this device
72 @retval EFI_ALREADY_STARTED This driver is already running on this device
73 @retval other This driver does not support this device
74
75 **/
76 EFI_STATUS
77 EFIAPI
78 PxeBcDriverBindingSupported (
79 IN EFI_DRIVER_BINDING_PROTOCOL * This,
80 IN EFI_HANDLE ControllerHandle,
81 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
82 )
83 {
84 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
85 EFI_STATUS Status;
86
87 Status = gBS->OpenProtocol (
88 ControllerHandle,
89 &gEfiPxeBaseCodeProtocolGuid,
90 (VOID **) &PxeBc,
91 This->DriverBindingHandle,
92 ControllerHandle,
93 EFI_OPEN_PROTOCOL_GET_PROTOCOL
94 );
95
96 if (!EFI_ERROR (Status)) {
97 return EFI_ALREADY_STARTED;
98 }
99
100 Status = gBS->OpenProtocol (
101 ControllerHandle,
102 &gEfiDhcp4ServiceBindingProtocolGuid,
103 NULL,
104 This->DriverBindingHandle,
105 ControllerHandle,
106 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
107 );
108
109 if (!EFI_ERROR (Status)) {
110
111 Status = gBS->OpenProtocol (
112 ControllerHandle,
113 &gEfiMtftp4ServiceBindingProtocolGuid,
114 NULL,
115 This->DriverBindingHandle,
116 ControllerHandle,
117 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
118 );
119
120 }
121
122 return Status;
123 }
124
125
126 /**
127 Start this driver on ControllerHandle. This service is called by the
128 EFI boot service ConnectController(). In order to make
129 drivers as small as possible, there are a few calling restrictions for
130 this service. ConnectController() must follow these
131 calling restrictions. If any other agent wishes to call Start() it
132 must also follow these calling restrictions.
133
134 @param This Protocol instance pointer.
135 @param ControllerHandle Handle of device to bind driver to
136 @param RemainingDevicePath Optional parameter use to pick a specific child
137 device to start.
138
139 @retval EFI_SUCCESS This driver is added to ControllerHandle
140 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
141 @retval other This driver does not support this device
142
143 **/
144 EFI_STATUS
145 EFIAPI
146 PxeBcDriverBindingStart (
147 IN EFI_DRIVER_BINDING_PROTOCOL * This,
148 IN EFI_HANDLE ControllerHandle,
149 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
150 )
151 {
152 PXEBC_PRIVATE_DATA *Private;
153 UINTN Index;
154 EFI_STATUS Status;
155 EFI_IP4_MODE_DATA Ip4ModeData;
156
157 Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
158 if (Private == NULL) {
159 return EFI_OUT_OF_RESOURCES;
160 }
161
162 Private->Signature = PXEBC_PRIVATE_DATA_SIGNATURE;
163 Private->Controller = ControllerHandle;
164 Private->Image = This->DriverBindingHandle;
165 CopyMem (&Private->PxeBc, &mPxeBcProtocolTemplate, sizeof (Private->PxeBc));
166 Private->PxeBc.Mode = &Private->Mode;
167 CopyMem (&Private->LoadFile, &mLoadFileProtocolTemplate, sizeof (Private->LoadFile));
168
169 Private->ProxyOffer.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
170 Private->Dhcp4Ack.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
171 Private->PxeReply.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
172
173 for (Index = 0; Index < PXEBC_MAX_OFFER_NUM; Index++) {
174 Private->Dhcp4Offers[Index].Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
175 }
176
177 //
178 // Get the NII interface if it exists.
179 //
180 Status = gBS->OpenProtocol (
181 ControllerHandle,
182 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
183 (VOID **) &Private->Nii,
184 This->DriverBindingHandle,
185 ControllerHandle,
186 EFI_OPEN_PROTOCOL_GET_PROTOCOL
187 );
188 if (EFI_ERROR (Status)) {
189 Private->Nii = NULL;
190 }
191
192 Status = NetLibCreateServiceChild (
193 ControllerHandle,
194 This->DriverBindingHandle,
195 &gEfiArpServiceBindingProtocolGuid,
196 &Private->ArpChild
197 );
198 if (EFI_ERROR (Status)) {
199 goto ON_ERROR;
200 }
201
202 Status = gBS->OpenProtocol (
203 Private->ArpChild,
204 &gEfiArpProtocolGuid,
205 (VOID **) &Private->Arp,
206 This->DriverBindingHandle,
207 ControllerHandle,
208 EFI_OPEN_PROTOCOL_BY_DRIVER
209 );
210 if (EFI_ERROR (Status)) {
211 goto ON_ERROR;
212 }
213
214 Status = NetLibCreateServiceChild (
215 ControllerHandle,
216 This->DriverBindingHandle,
217 &gEfiDhcp4ServiceBindingProtocolGuid,
218 &Private->Dhcp4Child
219 );
220 if (EFI_ERROR (Status)) {
221 goto ON_ERROR;
222 }
223
224 Status = gBS->OpenProtocol (
225 Private->Dhcp4Child,
226 &gEfiDhcp4ProtocolGuid,
227 (VOID **) &Private->Dhcp4,
228 This->DriverBindingHandle,
229 ControllerHandle,
230 EFI_OPEN_PROTOCOL_BY_DRIVER
231 );
232 if (EFI_ERROR (Status)) {
233 goto ON_ERROR;
234 }
235
236 Status = NetLibCreateServiceChild (
237 ControllerHandle,
238 This->DriverBindingHandle,
239 &gEfiIp4ServiceBindingProtocolGuid,
240 &Private->Ip4Child
241 );
242 if (EFI_ERROR (Status)) {
243 goto ON_ERROR;
244 }
245
246 Status = gBS->OpenProtocol (
247 Private->Ip4Child,
248 &gEfiIp4ProtocolGuid,
249 (VOID **) &Private->Ip4,
250 This->DriverBindingHandle,
251 ControllerHandle,
252 EFI_OPEN_PROTOCOL_BY_DRIVER
253 );
254 if (EFI_ERROR (Status)) {
255 goto ON_ERROR;
256 }
257
258 //
259 // Get max packet size from Ip4 to calculate block size for Tftp later.
260 //
261 Status = Private->Ip4->GetModeData (Private->Ip4, &Ip4ModeData, NULL, NULL);
262 if (EFI_ERROR (Status)) {
263 goto ON_ERROR;
264 }
265
266 Private->Ip4MaxPacketSize = Ip4ModeData.MaxPacketSize;
267
268 Status = NetLibCreateServiceChild (
269 ControllerHandle,
270 This->DriverBindingHandle,
271 &gEfiMtftp4ServiceBindingProtocolGuid,
272 &Private->Mtftp4Child
273 );
274
275 if (EFI_ERROR (Status)) {
276 goto ON_ERROR;
277 }
278
279 Status = gBS->OpenProtocol (
280 Private->Mtftp4Child,
281 &gEfiMtftp4ProtocolGuid,
282 (VOID **) &Private->Mtftp4,
283 This->DriverBindingHandle,
284 ControllerHandle,
285 EFI_OPEN_PROTOCOL_BY_DRIVER
286 );
287
288 if (EFI_ERROR (Status)) {
289 goto ON_ERROR;
290 }
291
292 Status = NetLibCreateServiceChild (
293 ControllerHandle,
294 This->DriverBindingHandle,
295 &gEfiUdp4ServiceBindingProtocolGuid,
296 &Private->Udp4ReadChild
297 );
298
299 if (EFI_ERROR (Status)) {
300 goto ON_ERROR;
301 }
302
303 //
304 // The UDP instance for EfiPxeBcUdpRead
305 //
306 Status = gBS->OpenProtocol (
307 Private->Udp4ReadChild,
308 &gEfiUdp4ProtocolGuid,
309 (VOID **) &Private->Udp4Read,
310 This->DriverBindingHandle,
311 ControllerHandle,
312 EFI_OPEN_PROTOCOL_BY_DRIVER
313 );
314
315 if (EFI_ERROR (Status)) {
316 goto ON_ERROR;
317 }
318
319 //
320 // The UDP instance for EfiPxeBcUdpWrite
321 //
322 Status = NetLibCreateServiceChild (
323 ControllerHandle,
324 This->DriverBindingHandle,
325 &gEfiUdp4ServiceBindingProtocolGuid,
326 &Private->Udp4WriteChild
327 );
328 if (EFI_ERROR (Status)) {
329 goto ON_ERROR;
330 }
331
332 Status = gBS->OpenProtocol (
333 Private->Udp4WriteChild,
334 &gEfiUdp4ProtocolGuid,
335 (VOID **) &Private->Udp4Write,
336 This->DriverBindingHandle,
337 ControllerHandle,
338 EFI_OPEN_PROTOCOL_BY_DRIVER
339 );
340 if (EFI_ERROR (Status)) {
341 goto ON_ERROR;
342 }
343 ZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA));
344 Private->Udp4CfgData.AcceptBroadcast = FALSE;
345 Private->Udp4CfgData.AcceptPromiscuous = FALSE;
346 Private->Udp4CfgData.AcceptAnyPort = TRUE;
347 Private->Udp4CfgData.AllowDuplicatePort = TRUE;
348 Private->Udp4CfgData.TypeOfService = DEFAULT_ToS;
349 Private->Udp4CfgData.TimeToLive = DEFAULT_TTL;
350 Private->Udp4CfgData.DoNotFragment = FALSE;
351 Private->Udp4CfgData.ReceiveTimeout = PXEBC_DEFAULT_LIFETIME;
352 Private->Udp4CfgData.UseDefaultAddress = FALSE;
353
354 PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4Read);
355 Private->MacLen = Private->SeedPacket.Dhcp4.Header.HwAddrLen;
356 CopyMem (&Private->Mac, &Private->SeedPacket.Dhcp4.Header.ClientHwAddr[0], Private->MacLen);
357
358
359 ZeroMem (&Private->Ip4ConfigData, sizeof (EFI_IP4_CONFIG_DATA));
360 Private->Ip4ConfigData.DefaultProtocol = EFI_IP_PROTO_ICMP;
361 Private->Ip4ConfigData.AcceptIcmpErrors = TRUE;
362 Private->Ip4ConfigData.TypeOfService = DEFAULT_ToS;
363 Private->Ip4ConfigData.TimeToLive = DEFAULT_TTL;
364 Private->Ip4ConfigData.DoNotFragment = FALSE;
365 Private->Ip4ConfigData.RawData = FALSE;
366
367 Status = gBS->InstallMultipleProtocolInterfaces (
368 &ControllerHandle,
369 &gEfiPxeBaseCodeProtocolGuid,
370 &Private->PxeBc,
371 &gEfiLoadFileProtocolGuid,
372 &Private->LoadFile,
373 NULL
374 );
375 if (EFI_ERROR (Status)) {
376 goto ON_ERROR;
377 }
378
379 return EFI_SUCCESS;
380
381 ON_ERROR:
382
383 if (Private->Udp4WriteChild != NULL) {
384 gBS->CloseProtocol (
385 Private->Udp4WriteChild,
386 &gEfiUdp4ProtocolGuid,
387 This->DriverBindingHandle,
388 ControllerHandle
389 );
390 NetLibDestroyServiceChild (
391 ControllerHandle,
392 This->DriverBindingHandle,
393 &gEfiUdp4ServiceBindingProtocolGuid,
394 Private->Udp4WriteChild
395 );
396 }
397
398 if (Private->Udp4ReadChild != NULL) {
399 gBS->CloseProtocol (
400 Private->Udp4ReadChild,
401 &gEfiUdp4ProtocolGuid,
402 This->DriverBindingHandle,
403 ControllerHandle
404 );
405 NetLibDestroyServiceChild (
406 ControllerHandle,
407 This->DriverBindingHandle,
408 &gEfiUdp4ServiceBindingProtocolGuid,
409 Private->Udp4ReadChild
410 );
411 }
412
413 if (Private->Mtftp4Child != NULL) {
414 gBS->CloseProtocol (
415 Private->Mtftp4Child,
416 &gEfiMtftp4ProtocolGuid,
417 This->DriverBindingHandle,
418 ControllerHandle
419 );
420
421 NetLibDestroyServiceChild (
422 ControllerHandle,
423 This->DriverBindingHandle,
424 &gEfiMtftp4ServiceBindingProtocolGuid,
425 Private->Mtftp4Child
426 );
427 }
428
429 if (Private->Ip4Child != NULL) {
430 gBS->CloseProtocol (
431 Private->Ip4Child,
432 &gEfiIp4ProtocolGuid,
433 This->DriverBindingHandle,
434 ControllerHandle
435 );
436
437 NetLibDestroyServiceChild (
438 ControllerHandle,
439 This->DriverBindingHandle,
440 &gEfiIp4ServiceBindingProtocolGuid,
441 Private->Ip4Child
442 );
443 }
444
445 if (Private->Dhcp4Child != NULL) {
446 gBS->CloseProtocol (
447 Private->Dhcp4Child,
448 &gEfiDhcp4ProtocolGuid,
449 This->DriverBindingHandle,
450 ControllerHandle
451 );
452
453 NetLibDestroyServiceChild (
454 ControllerHandle,
455 This->DriverBindingHandle,
456 &gEfiDhcp4ServiceBindingProtocolGuid,
457 Private->Dhcp4Child
458 );
459 }
460
461 if (Private->ArpChild != NULL) {
462 gBS->CloseProtocol (
463 Private->ArpChild,
464 &gEfiArpProtocolGuid,
465 This->DriverBindingHandle,
466 ControllerHandle
467 );
468
469 NetLibDestroyServiceChild (
470 ControllerHandle,
471 This->DriverBindingHandle,
472 &gEfiArpServiceBindingProtocolGuid,
473 Private->ArpChild
474 );
475 }
476
477 FreePool (Private);
478
479 return Status;
480 }
481
482
483 /**
484 Stop this driver on ControllerHandle. This service is called by the
485 EFI boot service DisconnectController(). In order to
486 make drivers as small as possible, there are a few calling
487 restrictions for this service. DisconnectController()
488 must follow these calling restrictions. If any other agent wishes
489 to call Stop() it must also follow these calling restrictions.
490
491 @param This Protocol instance pointer.
492 @param ControllerHandle Handle of device to stop driver on
493 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
494 children is zero stop the entire bus driver.
495 @param ChildHandleBuffer List of Child Handles to Stop.
496
497 @retval EFI_SUCCESS This driver is removed ControllerHandle
498 @retval other This driver was not removed from this device
499
500 **/
501 EFI_STATUS
502 EFIAPI
503 PxeBcDriverBindingStop (
504 IN EFI_DRIVER_BINDING_PROTOCOL *This,
505 IN EFI_HANDLE ControllerHandle,
506 IN UINTN NumberOfChildren,
507 IN EFI_HANDLE *ChildHandleBuffer
508 )
509 {
510 PXEBC_PRIVATE_DATA *Private;
511 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
512 EFI_HANDLE NicHandle;
513 EFI_STATUS Status;
514
515 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
516 if (NicHandle == NULL) {
517 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
518
519 if (NicHandle == NULL) {
520 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
521
522 if (NicHandle == NULL) {
523 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
524
525 if (NicHandle == NULL) {
526 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
527
528 if (NicHandle == NULL) {
529 return EFI_SUCCESS;
530 }
531 }
532 }
533 }
534 }
535
536 Status = gBS->OpenProtocol (
537 NicHandle,
538 &gEfiPxeBaseCodeProtocolGuid,
539 (VOID **) &PxeBc,
540 This->DriverBindingHandle,
541 ControllerHandle,
542 EFI_OPEN_PROTOCOL_GET_PROTOCOL
543 );
544
545 if (EFI_ERROR (Status)) {
546 return Status;
547 }
548
549 //
550 // Stop functionality of PXE Base Code protocol
551 //
552 Status = PxeBc->Stop (PxeBc);
553 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
554 return Status;
555 }
556
557 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);
558
559 Status = gBS->UninstallMultipleProtocolInterfaces (
560 NicHandle,
561 &gEfiPxeBaseCodeProtocolGuid,
562 &Private->PxeBc,
563 &gEfiLoadFileProtocolGuid,
564 &Private->LoadFile,
565 NULL
566 );
567
568 if (!EFI_ERROR (Status)) {
569
570 gBS->CloseProtocol (
571 Private->Udp4WriteChild,
572 &gEfiUdp4ProtocolGuid,
573 This->DriverBindingHandle,
574 NicHandle
575 );
576 NetLibDestroyServiceChild (
577 ControllerHandle,
578 This->DriverBindingHandle,
579 &gEfiUdp4ServiceBindingProtocolGuid,
580 Private->Udp4WriteChild
581 );
582
583 gBS->CloseProtocol (
584 Private->Udp4ReadChild,
585 &gEfiUdp4ProtocolGuid,
586 This->DriverBindingHandle,
587 NicHandle
588 );
589 NetLibDestroyServiceChild (
590 NicHandle,
591 This->DriverBindingHandle,
592 &gEfiUdp4ServiceBindingProtocolGuid,
593 Private->Udp4ReadChild
594 );
595
596 gBS->CloseProtocol (
597 Private->Dhcp4Child,
598 &gEfiDhcp4ProtocolGuid,
599 This->DriverBindingHandle,
600 NicHandle
601 );
602 NetLibDestroyServiceChild (
603 NicHandle,
604 This->DriverBindingHandle,
605 &gEfiDhcp4ServiceBindingProtocolGuid,
606 Private->Dhcp4Child
607 );
608
609 gBS->CloseProtocol (
610 Private->Mtftp4Child,
611 &gEfiMtftp4ProtocolGuid,
612 This->DriverBindingHandle,
613 NicHandle
614 );
615 NetLibDestroyServiceChild (
616 NicHandle,
617 This->DriverBindingHandle,
618 &gEfiMtftp4ServiceBindingProtocolGuid,
619 Private->Mtftp4Child
620 );
621
622 gBS->CloseProtocol (
623 Private->Ip4Child,
624 &gEfiIp4ProtocolGuid,
625 This->DriverBindingHandle,
626 NicHandle
627 );
628 NetLibDestroyServiceChild (
629 NicHandle,
630 This->DriverBindingHandle,
631 &gEfiIp4ServiceBindingProtocolGuid,
632 Private->Ip4Child
633 );
634
635 gBS->CloseProtocol (
636 Private->ArpChild,
637 &gEfiArpProtocolGuid,
638 This->DriverBindingHandle,
639 NicHandle
640 );
641 NetLibDestroyServiceChild (
642 NicHandle,
643 This->DriverBindingHandle,
644 &gEfiArpServiceBindingProtocolGuid,
645 Private->ArpChild
646 );
647
648 FreePool (Private);
649 }
650
651 return Status;
652 }
653
654