1 /** @file
2 The driver binding for UEFI PXEBC protocol.
3
4 Copyright (c) 2007 - 2015, 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
PxeBcDriverEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
PxeBcDriverBindingSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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
PxeBcDriverBindingStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL)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 // Locate Ip4->Ip4Config2 and store it for set IPv4 Policy.
380 //
381 Status = gBS->HandleProtocol (
382 ControllerHandle,
383 &gEfiIp4Config2ProtocolGuid,
384 (VOID **) &Private->Ip4Config2
385 );
386 if (EFI_ERROR (Status)) {
387 goto ON_ERROR;
388 }
389
390 return EFI_SUCCESS;
391
392 ON_ERROR:
393
394 if (Private->Udp4WriteChild != NULL) {
395 gBS->CloseProtocol (
396 Private->Udp4WriteChild,
397 &gEfiUdp4ProtocolGuid,
398 This->DriverBindingHandle,
399 ControllerHandle
400 );
401 NetLibDestroyServiceChild (
402 ControllerHandle,
403 This->DriverBindingHandle,
404 &gEfiUdp4ServiceBindingProtocolGuid,
405 Private->Udp4WriteChild
406 );
407 }
408
409 if (Private->Udp4ReadChild != NULL) {
410 gBS->CloseProtocol (
411 Private->Udp4ReadChild,
412 &gEfiUdp4ProtocolGuid,
413 This->DriverBindingHandle,
414 ControllerHandle
415 );
416 NetLibDestroyServiceChild (
417 ControllerHandle,
418 This->DriverBindingHandle,
419 &gEfiUdp4ServiceBindingProtocolGuid,
420 Private->Udp4ReadChild
421 );
422 }
423
424 if (Private->Mtftp4Child != NULL) {
425 gBS->CloseProtocol (
426 Private->Mtftp4Child,
427 &gEfiMtftp4ProtocolGuid,
428 This->DriverBindingHandle,
429 ControllerHandle
430 );
431
432 NetLibDestroyServiceChild (
433 ControllerHandle,
434 This->DriverBindingHandle,
435 &gEfiMtftp4ServiceBindingProtocolGuid,
436 Private->Mtftp4Child
437 );
438 }
439
440 if (Private->Ip4Child != NULL) {
441 gBS->CloseProtocol (
442 Private->Ip4Child,
443 &gEfiIp4ProtocolGuid,
444 This->DriverBindingHandle,
445 ControllerHandle
446 );
447
448 NetLibDestroyServiceChild (
449 ControllerHandle,
450 This->DriverBindingHandle,
451 &gEfiIp4ServiceBindingProtocolGuid,
452 Private->Ip4Child
453 );
454 }
455
456 if (Private->Dhcp4Child != NULL) {
457 gBS->CloseProtocol (
458 Private->Dhcp4Child,
459 &gEfiDhcp4ProtocolGuid,
460 This->DriverBindingHandle,
461 ControllerHandle
462 );
463
464 NetLibDestroyServiceChild (
465 ControllerHandle,
466 This->DriverBindingHandle,
467 &gEfiDhcp4ServiceBindingProtocolGuid,
468 Private->Dhcp4Child
469 );
470 }
471
472 if (Private->ArpChild != NULL) {
473 gBS->CloseProtocol (
474 Private->ArpChild,
475 &gEfiArpProtocolGuid,
476 This->DriverBindingHandle,
477 ControllerHandle
478 );
479
480 NetLibDestroyServiceChild (
481 ControllerHandle,
482 This->DriverBindingHandle,
483 &gEfiArpServiceBindingProtocolGuid,
484 Private->ArpChild
485 );
486 }
487
488 FreePool (Private);
489
490 return Status;
491 }
492
493
494 /**
495 Stop this driver on ControllerHandle. This service is called by the
496 EFI boot service DisconnectController(). In order to
497 make drivers as small as possible, there are a few calling
498 restrictions for this service. DisconnectController()
499 must follow these calling restrictions. If any other agent wishes
500 to call Stop() it must also follow these calling restrictions.
501
502 @param This Protocol instance pointer.
503 @param ControllerHandle Handle of device to stop driver on
504 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
505 children is zero stop the entire bus driver.
506 @param ChildHandleBuffer List of Child Handles to Stop.
507
508 @retval EFI_SUCCESS This driver is removed ControllerHandle
509 @retval other This driver was not removed from this device
510
511 **/
512 EFI_STATUS
513 EFIAPI
PxeBcDriverBindingStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)514 PxeBcDriverBindingStop (
515 IN EFI_DRIVER_BINDING_PROTOCOL *This,
516 IN EFI_HANDLE ControllerHandle,
517 IN UINTN NumberOfChildren,
518 IN EFI_HANDLE *ChildHandleBuffer
519 )
520 {
521 PXEBC_PRIVATE_DATA *Private;
522 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
523 EFI_HANDLE NicHandle;
524 EFI_STATUS Status;
525
526 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
527 if (NicHandle == NULL) {
528 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
529
530 if (NicHandle == NULL) {
531 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
532
533 if (NicHandle == NULL) {
534 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
535
536 if (NicHandle == NULL) {
537 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
538
539 if (NicHandle == NULL) {
540 return EFI_SUCCESS;
541 }
542 }
543 }
544 }
545 }
546
547 Status = gBS->OpenProtocol (
548 NicHandle,
549 &gEfiPxeBaseCodeProtocolGuid,
550 (VOID **) &PxeBc,
551 This->DriverBindingHandle,
552 ControllerHandle,
553 EFI_OPEN_PROTOCOL_GET_PROTOCOL
554 );
555
556 if (EFI_ERROR (Status)) {
557 return Status;
558 }
559
560 //
561 // Stop functionality of PXE Base Code protocol
562 //
563 Status = PxeBc->Stop (PxeBc);
564 if (Status != EFI_SUCCESS && Status != EFI_NOT_STARTED) {
565 return Status;
566 }
567
568 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);
569
570 Status = gBS->UninstallMultipleProtocolInterfaces (
571 NicHandle,
572 &gEfiPxeBaseCodeProtocolGuid,
573 &Private->PxeBc,
574 &gEfiLoadFileProtocolGuid,
575 &Private->LoadFile,
576 NULL
577 );
578
579 if (!EFI_ERROR (Status)) {
580
581 gBS->CloseProtocol (
582 Private->Udp4WriteChild,
583 &gEfiUdp4ProtocolGuid,
584 This->DriverBindingHandle,
585 NicHandle
586 );
587 NetLibDestroyServiceChild (
588 ControllerHandle,
589 This->DriverBindingHandle,
590 &gEfiUdp4ServiceBindingProtocolGuid,
591 Private->Udp4WriteChild
592 );
593
594 gBS->CloseProtocol (
595 Private->Udp4ReadChild,
596 &gEfiUdp4ProtocolGuid,
597 This->DriverBindingHandle,
598 NicHandle
599 );
600 NetLibDestroyServiceChild (
601 NicHandle,
602 This->DriverBindingHandle,
603 &gEfiUdp4ServiceBindingProtocolGuid,
604 Private->Udp4ReadChild
605 );
606
607 gBS->CloseProtocol (
608 Private->Dhcp4Child,
609 &gEfiDhcp4ProtocolGuid,
610 This->DriverBindingHandle,
611 NicHandle
612 );
613 NetLibDestroyServiceChild (
614 NicHandle,
615 This->DriverBindingHandle,
616 &gEfiDhcp4ServiceBindingProtocolGuid,
617 Private->Dhcp4Child
618 );
619
620 gBS->CloseProtocol (
621 Private->Mtftp4Child,
622 &gEfiMtftp4ProtocolGuid,
623 This->DriverBindingHandle,
624 NicHandle
625 );
626 NetLibDestroyServiceChild (
627 NicHandle,
628 This->DriverBindingHandle,
629 &gEfiMtftp4ServiceBindingProtocolGuid,
630 Private->Mtftp4Child
631 );
632
633 gBS->CloseProtocol (
634 Private->Ip4Child,
635 &gEfiIp4ProtocolGuid,
636 This->DriverBindingHandle,
637 NicHandle
638 );
639 NetLibDestroyServiceChild (
640 NicHandle,
641 This->DriverBindingHandle,
642 &gEfiIp4ServiceBindingProtocolGuid,
643 Private->Ip4Child
644 );
645
646 gBS->CloseProtocol (
647 Private->ArpChild,
648 &gEfiArpProtocolGuid,
649 This->DriverBindingHandle,
650 NicHandle
651 );
652 NetLibDestroyServiceChild (
653 NicHandle,
654 This->DriverBindingHandle,
655 &gEfiArpServiceBindingProtocolGuid,
656 Private->ArpChild
657 );
658
659 FreePool (Private);
660 }
661
662 return Status;
663 }
664
665
666