1. sync PXE boot trackers for Windows 2008 server.
[edk2.git] / MdeModulePkg / Universal / Network / UefiPxeBcDxe / PxeBcDriver.c
blob77c3077b5e77d8613d8e0a2d82724f725126bbf0
1 /** @file
2 The driver binding for UEFI PXEBC protocol.
4 Copyright (c) 2007 - 2008, Intel Corporation.<BR>
5 All rights reserved. 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
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.
13 **/
16 #include "PxeBcImpl.h"
18 EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = {
19 PxeBcDriverBindingSupported,
20 PxeBcDriverBindingStart,
21 PxeBcDriverBindingStop,
22 0xa,
23 NULL,
24 NULL
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.
32 @param ImageHandle The firmware allocated handle for the UEFI image.
33 @param SystemTable A pointer to the EFI System Table.
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.
38 **/
39 EFI_STATUS
40 PxeBcDriverEntryPoint (
41 IN EFI_HANDLE ImageHandle,
42 IN EFI_SYSTEM_TABLE *SystemTable
45 return EfiLibInstallDriverBindingComponentName2 (
46 ImageHandle,
47 SystemTable,
48 &gPxeBcDriverBinding,
49 ImageHandle,
50 &gPxeBcComponentName,
51 &gPxeBcComponentName2
56 /**
57 Test to see if this driver supports ControllerHandle. This service
58 is called by the EFI boot service ConnectController(). In
59 order to make drivers as small as possible, there are a few calling
60 restrictions for this service. ConnectController() must
61 follow these calling restrictions. If any other agent wishes to call
62 Supported() it must also follow these calling restrictions.
63 PxeBc requires DHCP4 and MTFTP4 protocols.
65 @param This Protocol instance pointer.
66 @param ControllerHandle Handle of device to test
67 @param RemainingDevicePath Optional parameter use to pick a specific child
68 device to start.
70 @retval EFI_SUCCESS This driver supports this device
71 @retval EFI_ALREADY_STARTED This driver is already running on this device
72 @retval other This driver does not support this device
74 **/
75 EFI_STATUS
76 EFIAPI
77 PxeBcDriverBindingSupported (
78 IN EFI_DRIVER_BINDING_PROTOCOL * This,
79 IN EFI_HANDLE ControllerHandle,
80 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
83 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
84 EFI_STATUS Status;
86 Status = gBS->OpenProtocol (
87 ControllerHandle,
88 &gEfiPxeBaseCodeProtocolGuid,
89 (VOID **) &PxeBc,
90 This->DriverBindingHandle,
91 ControllerHandle,
92 EFI_OPEN_PROTOCOL_GET_PROTOCOL
95 if (!EFI_ERROR (Status)) {
96 return EFI_ALREADY_STARTED;
99 Status = gBS->OpenProtocol (
100 ControllerHandle,
101 &gEfiDhcp4ServiceBindingProtocolGuid,
102 NULL,
103 This->DriverBindingHandle,
104 ControllerHandle,
105 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
108 if (!EFI_ERROR (Status)) {
110 Status = gBS->OpenProtocol (
111 ControllerHandle,
112 &gEfiMtftp4ServiceBindingProtocolGuid,
113 NULL,
114 This->DriverBindingHandle,
115 ControllerHandle,
116 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
121 return Status;
126 Start this driver on ControllerHandle. This service is called by the
127 EFI boot service ConnectController(). In order to make
128 drivers as small as possible, there are a few calling restrictions for
129 this service. ConnectController() must follow these
130 calling restrictions. If any other agent wishes to call Start() it
131 must also follow these calling restrictions.
133 @param This Protocol instance pointer.
134 @param ControllerHandle Handle of device to bind driver to
135 @param RemainingDevicePath Optional parameter use to pick a specific child
136 device to start.
138 @retval EFI_SUCCESS This driver is added to ControllerHandle
139 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
140 @retval other This driver does not support this device
143 EFI_STATUS
144 EFIAPI
145 PxeBcDriverBindingStart (
146 IN EFI_DRIVER_BINDING_PROTOCOL * This,
147 IN EFI_HANDLE ControllerHandle,
148 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL
151 PXEBC_PRIVATE_DATA *Private;
152 UINTN Index;
153 EFI_STATUS Status;
155 Private = AllocateZeroPool (sizeof (PXEBC_PRIVATE_DATA));
156 if (Private == NULL) {
157 return EFI_OUT_OF_RESOURCES;
160 Private->Signature = PXEBC_PRIVATE_DATA_SIGNATURE;
161 Private->Controller = ControllerHandle;
162 Private->Image = This->DriverBindingHandle;
163 CopyMem (&Private->PxeBc, &mPxeBcProtocolTemplate, sizeof (Private->PxeBc));
164 Private->PxeBc.Mode = &Private->Mode;
165 CopyMem (&Private->LoadFile, &mLoadFileProtocolTemplate, sizeof (Private->LoadFile));
167 Private->ProxyOffer.Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
168 Private->Dhcp4Ack.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
169 Private->PxeReply.Packet.Ack.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
171 for (Index = 0; Index < PXEBC_MAX_OFFER_NUM; Index++) {
172 Private->Dhcp4Offers[Index].Packet.Offer.Size = PXEBC_CACHED_DHCP4_PACKET_MAX_SIZE;
176 // Get the NII interface
178 Status = gBS->OpenProtocol (
179 ControllerHandle,
180 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
181 (VOID **) &Private->Nii,
182 This->DriverBindingHandle,
183 ControllerHandle,
184 EFI_OPEN_PROTOCOL_GET_PROTOCOL
186 if (EFI_ERROR (Status)) {
187 goto ON_ERROR;
190 Status = NetLibCreateServiceChild (
191 ControllerHandle,
192 This->DriverBindingHandle,
193 &gEfiArpServiceBindingProtocolGuid,
194 &Private->ArpChild
196 if (EFI_ERROR (Status)) {
197 goto ON_ERROR;
200 Status = gBS->OpenProtocol (
201 Private->ArpChild,
202 &gEfiArpProtocolGuid,
203 (VOID **) &Private->Arp,
204 This->DriverBindingHandle,
205 ControllerHandle,
206 EFI_OPEN_PROTOCOL_BY_DRIVER
208 if (EFI_ERROR (Status)) {
209 goto ON_ERROR;
212 Status = NetLibCreateServiceChild (
213 ControllerHandle,
214 This->DriverBindingHandle,
215 &gEfiDhcp4ServiceBindingProtocolGuid,
216 &Private->Dhcp4Child
218 if (EFI_ERROR (Status)) {
219 goto ON_ERROR;
222 Status = gBS->OpenProtocol (
223 Private->Dhcp4Child,
224 &gEfiDhcp4ProtocolGuid,
225 (VOID **) &Private->Dhcp4,
226 This->DriverBindingHandle,
227 ControllerHandle,
228 EFI_OPEN_PROTOCOL_BY_DRIVER
230 if (EFI_ERROR (Status)) {
231 goto ON_ERROR;
234 Status = NetLibCreateServiceChild (
235 ControllerHandle,
236 This->DriverBindingHandle,
237 &gEfiIp4ServiceBindingProtocolGuid,
238 &Private->Ip4Child
240 if (EFI_ERROR (Status)) {
241 goto ON_ERROR;
244 Status = gBS->OpenProtocol (
245 Private->Ip4Child,
246 &gEfiIp4ProtocolGuid,
247 (VOID **) &Private->Ip4,
248 This->DriverBindingHandle,
249 ControllerHandle,
250 EFI_OPEN_PROTOCOL_BY_DRIVER
252 if (EFI_ERROR (Status)) {
253 goto ON_ERROR;
256 Status = NetLibCreateServiceChild (
257 ControllerHandle,
258 This->DriverBindingHandle,
259 &gEfiMtftp4ServiceBindingProtocolGuid,
260 &Private->Mtftp4Child
263 if (EFI_ERROR (Status)) {
264 goto ON_ERROR;
267 Status = gBS->OpenProtocol (
268 Private->Mtftp4Child,
269 &gEfiMtftp4ProtocolGuid,
270 (VOID **) &Private->Mtftp4,
271 This->DriverBindingHandle,
272 ControllerHandle,
273 EFI_OPEN_PROTOCOL_BY_DRIVER
276 if (EFI_ERROR (Status)) {
277 goto ON_ERROR;
280 Status = NetLibCreateServiceChild (
281 ControllerHandle,
282 This->DriverBindingHandle,
283 &gEfiUdp4ServiceBindingProtocolGuid,
284 &Private->Udp4ReadChild
287 if (EFI_ERROR (Status)) {
288 goto ON_ERROR;
292 // The UDP instance for EfiPxeBcUdpRead
294 Status = gBS->OpenProtocol (
295 Private->Udp4ReadChild,
296 &gEfiUdp4ProtocolGuid,
297 (VOID **) &Private->Udp4Read,
298 This->DriverBindingHandle,
299 ControllerHandle,
300 EFI_OPEN_PROTOCOL_BY_DRIVER
303 if (EFI_ERROR (Status)) {
304 goto ON_ERROR;
308 // The UDP instance for EfiPxeBcUdpWrite
310 Status = NetLibCreateServiceChild (
311 ControllerHandle,
312 This->DriverBindingHandle,
313 &gEfiUdp4ServiceBindingProtocolGuid,
314 &Private->Udp4WriteChild
316 if (EFI_ERROR (Status)) {
317 goto ON_ERROR;
320 Status = gBS->OpenProtocol (
321 Private->Udp4WriteChild,
322 &gEfiUdp4ProtocolGuid,
323 (VOID **) &Private->Udp4Write,
324 This->DriverBindingHandle,
325 ControllerHandle,
326 EFI_OPEN_PROTOCOL_BY_DRIVER
328 if (EFI_ERROR (Status)) {
329 goto ON_ERROR;
331 ZeroMem (&Private->Udp4CfgData, sizeof (EFI_UDP4_CONFIG_DATA));
332 Private->Udp4CfgData.AcceptBroadcast = TRUE;
333 Private->Udp4CfgData.AcceptPromiscuous = FALSE;
334 Private->Udp4CfgData.AcceptAnyPort = TRUE;
335 Private->Udp4CfgData.AllowDuplicatePort = TRUE;
336 Private->Udp4CfgData.TypeOfService = DEFAULT_ToS;
337 Private->Udp4CfgData.TimeToLive = DEFAULT_TTL;
338 Private->Udp4CfgData.DoNotFragment = FALSE;
339 Private->Udp4CfgData.ReceiveTimeout = 50000; // 50 milliseconds
340 Private->Udp4CfgData.UseDefaultAddress = FALSE;
342 PxeBcInitSeedPacket (&Private->SeedPacket, Private->Udp4Read);
343 Private->MacLen = Private->SeedPacket.Dhcp4.Header.HwAddrLen;
344 CopyMem (&Private->Mac, &Private->SeedPacket.Dhcp4.Header.ClientHwAddr[0], Private->MacLen);
347 ZeroMem (&Private->Ip4ConfigData, sizeof (EFI_IP4_CONFIG_DATA));
348 Private->Ip4ConfigData.DefaultProtocol = EFI_IP_PROTO_ICMP;
349 Private->Ip4ConfigData.AcceptIcmpErrors = TRUE;
350 Private->Ip4ConfigData.TypeOfService = DEFAULT_ToS;
351 Private->Ip4ConfigData.TimeToLive = DEFAULT_TTL;
352 Private->Ip4ConfigData.DoNotFragment = FALSE;
353 Private->Ip4ConfigData.RawData = FALSE;
355 Status = gBS->InstallMultipleProtocolInterfaces (
356 &ControllerHandle,
357 &gEfiPxeBaseCodeProtocolGuid,
358 &Private->PxeBc,
359 &gEfiLoadFileProtocolGuid,
360 &Private->LoadFile,
361 NULL
363 if (EFI_ERROR (Status)) {
364 goto ON_ERROR;
367 return EFI_SUCCESS;
369 ON_ERROR:
371 if (Private->Udp4WriteChild != NULL) {
372 gBS->CloseProtocol (
373 Private->Udp4WriteChild,
374 &gEfiUdp4ProtocolGuid,
375 This->DriverBindingHandle,
376 ControllerHandle
378 NetLibDestroyServiceChild (
379 ControllerHandle,
380 This->DriverBindingHandle,
381 &gEfiUdp4ServiceBindingProtocolGuid,
382 Private->Udp4WriteChild
386 if (Private->Udp4ReadChild != NULL) {
387 gBS->CloseProtocol (
388 Private->Udp4ReadChild,
389 &gEfiUdp4ProtocolGuid,
390 This->DriverBindingHandle,
391 ControllerHandle
393 NetLibDestroyServiceChild (
394 ControllerHandle,
395 This->DriverBindingHandle,
396 &gEfiUdp4ServiceBindingProtocolGuid,
397 Private->Udp4ReadChild
401 if (Private->Mtftp4Child != NULL) {
402 gBS->CloseProtocol (
403 Private->Mtftp4Child,
404 &gEfiMtftp4ProtocolGuid,
405 This->DriverBindingHandle,
406 ControllerHandle
409 NetLibDestroyServiceChild (
410 ControllerHandle,
411 This->DriverBindingHandle,
412 &gEfiMtftp4ServiceBindingProtocolGuid,
413 Private->Mtftp4Child
417 if (Private->Ip4Child != NULL) {
418 gBS->CloseProtocol (
419 Private->Ip4Child,
420 &gEfiIp4ProtocolGuid,
421 This->DriverBindingHandle,
422 ControllerHandle
425 NetLibDestroyServiceChild (
426 ControllerHandle,
427 This->DriverBindingHandle,
428 &gEfiIp4ServiceBindingProtocolGuid,
429 Private->Ip4Child
433 if (Private->Dhcp4Child != NULL) {
434 gBS->CloseProtocol (
435 Private->Dhcp4Child,
436 &gEfiDhcp4ProtocolGuid,
437 This->DriverBindingHandle,
438 ControllerHandle
441 NetLibDestroyServiceChild (
442 ControllerHandle,
443 This->DriverBindingHandle,
444 &gEfiDhcp4ServiceBindingProtocolGuid,
445 Private->Dhcp4Child
449 if (Private->ArpChild != NULL) {
450 gBS->CloseProtocol (
451 Private->ArpChild,
452 &gEfiArpProtocolGuid,
453 This->DriverBindingHandle,
454 ControllerHandle
457 NetLibDestroyServiceChild (
458 ControllerHandle,
459 This->DriverBindingHandle,
460 &gEfiArpServiceBindingProtocolGuid,
461 Private->ArpChild
465 gBS->FreePool (Private);
467 return Status;
472 Stop this driver on ControllerHandle. This service is called by the
473 EFI boot service DisconnectController(). In order to
474 make drivers as small as possible, there are a few calling
475 restrictions for this service. DisconnectController()
476 must follow these calling restrictions. If any other agent wishes
477 to call Stop() it must also follow these calling restrictions.
479 @param This Protocol instance pointer.
480 @param ControllerHandle Handle of device to stop driver on
481 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
482 children is zero stop the entire bus driver.
483 @param ChildHandleBuffer List of Child Handles to Stop.
485 @retval EFI_SUCCESS This driver is removed ControllerHandle
486 @retval other This driver was not removed from this device
489 EFI_STATUS
490 EFIAPI
491 PxeBcDriverBindingStop (
492 IN EFI_DRIVER_BINDING_PROTOCOL *This,
493 IN EFI_HANDLE ControllerHandle,
494 IN UINTN NumberOfChildren,
495 IN EFI_HANDLE *ChildHandleBuffer
498 PXEBC_PRIVATE_DATA *Private;
499 EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
500 EFI_HANDLE NicHandle;
501 EFI_STATUS Status;
503 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
504 if (NicHandle == NULL) {
505 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);
507 if (NicHandle == NULL) {
508 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiIp4ProtocolGuid);
510 if (NicHandle == NULL) {
511 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
513 if (NicHandle == NULL) {
514 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiMtftp4ProtocolGuid);
516 if (NicHandle == NULL) {
517 return EFI_DEVICE_ERROR;
524 Status = gBS->OpenProtocol (
525 NicHandle,
526 &gEfiPxeBaseCodeProtocolGuid,
527 (VOID **) &PxeBc,
528 This->DriverBindingHandle,
529 ControllerHandle,
530 EFI_OPEN_PROTOCOL_GET_PROTOCOL
533 if (EFI_ERROR (Status)) {
534 return Status;
537 Private = PXEBC_PRIVATE_DATA_FROM_PXEBC (PxeBc);
539 Status = gBS->UninstallMultipleProtocolInterfaces (
540 NicHandle,
541 &gEfiPxeBaseCodeProtocolGuid,
542 &Private->PxeBc,
543 &gEfiLoadFileProtocolGuid,
544 &Private->LoadFile,
545 NULL
548 if (!EFI_ERROR (Status)) {
550 gBS->CloseProtocol (
551 Private->Udp4WriteChild,
552 &gEfiUdp4ProtocolGuid,
553 This->DriverBindingHandle,
554 NicHandle
556 NetLibDestroyServiceChild (
557 ControllerHandle,
558 This->DriverBindingHandle,
559 &gEfiUdp4ServiceBindingProtocolGuid,
560 Private->Udp4WriteChild
563 gBS->CloseProtocol (
564 Private->Udp4ReadChild,
565 &gEfiUdp4ProtocolGuid,
566 This->DriverBindingHandle,
567 NicHandle
569 NetLibDestroyServiceChild (
570 NicHandle,
571 This->DriverBindingHandle,
572 &gEfiUdp4ServiceBindingProtocolGuid,
573 Private->Udp4ReadChild
576 gBS->CloseProtocol (
577 Private->Dhcp4Child,
578 &gEfiDhcp4ProtocolGuid,
579 This->DriverBindingHandle,
580 NicHandle
582 NetLibDestroyServiceChild (
583 NicHandle,
584 This->DriverBindingHandle,
585 &gEfiDhcp4ServiceBindingProtocolGuid,
586 Private->Dhcp4Child
589 gBS->CloseProtocol (
590 Private->Mtftp4Child,
591 &gEfiMtftp4ProtocolGuid,
592 This->DriverBindingHandle,
593 NicHandle
595 NetLibDestroyServiceChild (
596 NicHandle,
597 This->DriverBindingHandle,
598 &gEfiMtftp4ServiceBindingProtocolGuid,
599 Private->Mtftp4Child
602 gBS->CloseProtocol (
603 Private->Ip4Child,
604 &gEfiIp4ProtocolGuid,
605 This->DriverBindingHandle,
606 NicHandle
608 NetLibDestroyServiceChild (
609 NicHandle,
610 This->DriverBindingHandle,
611 &gEfiIp4ServiceBindingProtocolGuid,
612 Private->Ip4Child
615 gBS->CloseProtocol (
616 Private->ArpChild,
617 &gEfiArpProtocolGuid,
618 This->DriverBindingHandle,
619 NicHandle
621 NetLibDestroyServiceChild (
622 NicHandle,
623 This->DriverBindingHandle,
624 &gEfiArpServiceBindingProtocolGuid,
625 Private->ArpChild
628 gBS->FreePool (Private);
631 return Status;