3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
22 #include "Dhcp4Impl.h"
23 #include "Dhcp4Driver.h"
25 EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding
= {
26 Dhcp4DriverBindingSupported
,
27 Dhcp4DriverBindingStart
,
28 Dhcp4DriverBindingStop
,
34 EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplete
= {
35 Dhcp4ServiceBindingCreateChild
,
36 Dhcp4ServiceBindingDestroyChild
42 Dhcp4DriverEntryPoint (
43 IN EFI_HANDLE ImageHandle
,
44 IN EFI_SYSTEM_TABLE
*SystemTable
50 Entry point of the DHCP driver to install various protocols.
54 ImageHandle - The driver's image handle
55 SystemTable - The system table
59 EFI_SUCCESS - All the related protocols are installed.
60 Others - Failed to install the protocols.
64 return EfiLibInstallDriverBindingComponentName2 (
76 Test to see if DHCP driver supports the ControllerHandle.
78 @param This Protocol instance pointer.
79 @param ControllerHandle Handle of device to test
80 @param RemainingDevicePath Optional parameter use to pick a specific child
83 @retval EFI_SUCCES This driver supports this device
84 @retval other This driver does not support this device
89 Dhcp4DriverBindingSupported (
90 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
91 IN EFI_HANDLE ControllerHandle
,
92 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
97 Status
= gBS
->OpenProtocol (
99 &gEfiUdp4ServiceBindingProtocolGuid
,
101 This
->DriverBindingHandle
,
103 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
112 Configure the default UDP child to receive all the DHCP traffics
113 on this network interface.
115 @param UdpIo The UDP IO port to configure
116 @param Context The context to the function
118 @retval EFI_SUCCESS The UDP IO port is successfully configured.
119 @retval Others Failed to configure the UDP child.
124 IN UDP_IO_PORT
*UdpIo
,
128 EFI_UDP4_CONFIG_DATA UdpConfigData
;
130 UdpConfigData
.AcceptBroadcast
= TRUE
;
131 UdpConfigData
.AcceptPromiscuous
= FALSE
;
132 UdpConfigData
.AcceptAnyPort
= FALSE
;
133 UdpConfigData
.AllowDuplicatePort
= TRUE
;
134 UdpConfigData
.TypeOfService
= 0;
135 UdpConfigData
.TimeToLive
= 64;
136 UdpConfigData
.DoNotFragment
= FALSE
;
137 UdpConfigData
.ReceiveTimeout
= 0;
138 UdpConfigData
.TransmitTimeout
= 0;
140 UdpConfigData
.UseDefaultAddress
= FALSE
;
141 UdpConfigData
.StationPort
= DHCP_CLIENT_PORT
;
142 UdpConfigData
.RemotePort
= DHCP_SERVER_PORT
;
144 NetZeroMem (&UdpConfigData
.StationAddress
, sizeof (EFI_IPv4_ADDRESS
));
145 NetZeroMem (&UdpConfigData
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
146 NetZeroMem (&UdpConfigData
.RemoteAddress
, sizeof (EFI_IPv4_ADDRESS
));
148 return UdpIo
->Udp
->Configure (UdpIo
->Udp
, &UdpConfigData
);;
154 Destory the DHCP service. The Dhcp4 service may be partly initialized,
155 or partly destoried. If a resource is destoried, it is marked as so in
156 case the destory failed and being called again later.
158 @param DhcpSb The DHCP service instance to destory.
160 @retval EFI_SUCCESS The DHCP service is successfully closed.
165 IN DHCP_SERVICE
*DhcpSb
168 DhcpCleanLease (DhcpSb
);
170 if (DhcpSb
->UdpIo
!= NULL
) {
171 UdpIoFreePort (DhcpSb
->UdpIo
);
172 DhcpSb
->UdpIo
= NULL
;
175 if (DhcpSb
->Timer
!= NULL
) {
176 gBS
->SetTimer (DhcpSb
->Timer
, TimerCancel
, 0);
177 gBS
->CloseEvent (DhcpSb
->Timer
);
179 DhcpSb
->Timer
= NULL
;
188 Create a new DHCP service binding instance for the controller.
190 @param Controller The controller to install DHCP service binding
192 @param ImageHandle The driver's image handle
193 @param Service The variable to receive the created DHCP service
196 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource .
197 @retval EFI_SUCCESS The DHCP service instance is created.
202 IN EFI_HANDLE Controller
,
203 IN EFI_HANDLE ImageHandle
,
204 OUT DHCP_SERVICE
**Service
207 DHCP_SERVICE
*DhcpSb
;
211 DhcpSb
= NetAllocateZeroPool (sizeof (DHCP_SERVICE
));
213 if (DhcpSb
== NULL
) {
214 return EFI_OUT_OF_RESOURCES
;
217 DhcpSb
->Signature
= DHCP_SERVICE_SIGNATURE
;
218 DhcpSb
->ServiceBinding
= mDhcp4ServiceBindingTemplete
;
219 DhcpSb
->ServiceState
= DHCP_UNCONFIGED
;
220 DhcpSb
->InDestory
= FALSE
;
221 DhcpSb
->Controller
= Controller
;
222 DhcpSb
->Image
= ImageHandle
;
223 NetListInit (&DhcpSb
->Children
);
224 DhcpSb
->DhcpState
= Dhcp4Stopped
;
225 DhcpSb
->Xid
= NET_RANDOM (NetRandomInitSeed ());
228 // Create various resources, UdpIo, Timer, and get Mac address
230 Status
= gBS
->CreateEvent (
231 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
238 if (EFI_ERROR (Status
)) {
242 DhcpSb
->UdpIo
= UdpIoCreatePort (Controller
, ImageHandle
, DhcpConfigUdpIo
, NULL
);
244 if (DhcpSb
->UdpIo
== NULL
) {
245 Status
= EFI_OUT_OF_RESOURCES
;
249 DhcpSb
->HwLen
= (UINT8
) DhcpSb
->UdpIo
->SnpMode
.HwAddressSize
;
250 DhcpSb
->HwType
= DhcpSb
->UdpIo
->SnpMode
.IfType
;
251 CopyMem (&DhcpSb
->Mac
, &DhcpSb
->UdpIo
->SnpMode
.CurrentAddress
, sizeof (DhcpSb
->Mac
));
257 Dhcp4CloseService (DhcpSb
);
258 NetFreePool (DhcpSb
);
265 Start this driver on ControllerHandle.
267 @param This Protocol instance pointer.
268 @param ControllerHandle Handle of device to bind driver to
269 @param RemainingDevicePath Optional parameter use to pick a specific child
272 @retval EFI_SUCCES This driver is added to ControllerHandle
273 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
274 @retval other This driver does not support this device
279 Dhcp4DriverBindingStart (
280 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
281 IN EFI_HANDLE ControllerHandle
,
282 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
285 DHCP_SERVICE
*DhcpSb
;
289 // First: test for the DHCP4 Protocol
291 Status
= gBS
->OpenProtocol (
293 &gEfiDhcp4ServiceBindingProtocolGuid
,
295 This
->DriverBindingHandle
,
297 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
300 if (Status
== EFI_SUCCESS
) {
301 return EFI_ALREADY_STARTED
;
304 Status
= Dhcp4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &DhcpSb
);
306 if (EFI_ERROR (Status
)) {
310 Status
= gBS
->SetTimer (DhcpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
312 if (EFI_ERROR (Status
)) {
317 // Install the Dhcp4ServiceBinding Protocol onto ControlerHandle
319 Status
= gBS
->InstallMultipleProtocolInterfaces (
321 &gEfiDhcp4ServiceBindingProtocolGuid
,
322 &DhcpSb
->ServiceBinding
,
326 if (EFI_ERROR (Status
)) {
333 Dhcp4CloseService (DhcpSb
);
334 NetFreePool (DhcpSb
);
340 Stop this driver on ControllerHandle.
342 @param This Protocol instance pointer.
343 @param ControllerHandle Handle of device to stop driver on
344 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
345 of children is zero stop the entire bus driver.
346 @param ChildHandleBuffer List of Child Handles to Stop.
348 @retval EFI_SUCCES This driver is removed ControllerHandle
349 @retval other This driver was not removed from this device
354 Dhcp4DriverBindingStop (
355 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
356 IN EFI_HANDLE ControllerHandle
,
357 IN UINTN NumberOfChildren
,
358 IN EFI_HANDLE
*ChildHandleBuffer
361 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
362 DHCP_SERVICE
*DhcpSb
;
363 DHCP_PROTOCOL
*Instance
;
364 EFI_HANDLE NicHandle
;
369 // DHCP driver opens UDP child, So, the ControllerHandle is the
370 // UDP child handle. locate the Nic handle first.
372 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp4ProtocolGuid
);
374 if (NicHandle
== NULL
) {
378 Status
= gBS
->OpenProtocol (
380 &gEfiDhcp4ServiceBindingProtocolGuid
,
381 (VOID
**) &ServiceBinding
,
382 This
->DriverBindingHandle
,
384 EFI_OPEN_PROTOCOL_GET_PROTOCOL
387 if (EFI_ERROR (Status
)) {
388 return EFI_DEVICE_ERROR
;
391 DhcpSb
= DHCP_SERVICE_FROM_THIS (ServiceBinding
);
393 if (DhcpSb
->InDestory
) {
397 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
398 DhcpSb
->InDestory
= TRUE
;
401 // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild
402 // may cause other child to be deleted.
404 while (!NetListIsEmpty (&DhcpSb
->Children
)) {
405 Instance
= NET_LIST_HEAD (&DhcpSb
->Children
, DHCP_PROTOCOL
, Link
);
406 Dhcp4ServiceBindingDestroyChild (ServiceBinding
, Instance
->Handle
);
409 if (DhcpSb
->NumChildren
!= 0) {
410 Status
= EFI_DEVICE_ERROR
;
414 DhcpSb
->ServiceState
= DHCP_DESTORY
;
416 Status
= gBS
->UninstallProtocolInterface (
418 &gEfiDhcp4ServiceBindingProtocolGuid
,
422 if (EFI_ERROR (Status
)) {
426 Dhcp4CloseService (DhcpSb
);
427 NET_RESTORE_TPL (OldTpl
);
429 NetFreePool (DhcpSb
);
433 DhcpSb
->InDestory
= FALSE
;
434 NET_RESTORE_TPL (OldTpl
);
440 Initialize a new DHCP child
442 @param DhcpSb The dhcp service instance
443 @param Instance The dhcp instance to initialize
450 IN DHCP_SERVICE
*DhcpSb
,
451 IN DHCP_PROTOCOL
*Instance
454 Instance
->Signature
= DHCP_PROTOCOL_SIGNATURE
;
455 CopyMem (&Instance
->Dhcp4Protocol
, &mDhcp4ProtocolTemplate
, sizeof (Instance
->Dhcp4Protocol
));
456 NetListInit (&Instance
->Link
);
457 Instance
->Handle
= NULL
;
458 Instance
->Service
= DhcpSb
;
459 Instance
->InDestory
= FALSE
;
460 Instance
->CompletionEvent
= NULL
;
461 Instance
->RenewRebindEvent
= NULL
;
462 Instance
->Token
= NULL
;
467 Creates a child handle with a set of DHCP4 services.
469 @param This Protocol instance pointer.
470 @param ChildHandle Pointer to the handle of the child to create. If
471 it is NULL, then a new handle is created. If it
472 is not NULL, then the DHCP4 services are added to
473 the existing child handle.
475 @retval EFI_SUCCES The child handle was created with the DHCP4
477 @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the child
478 @retval other The child handle was not created
483 Dhcp4ServiceBindingCreateChild (
484 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
485 IN EFI_HANDLE
*ChildHandle
488 DHCP_SERVICE
*DhcpSb
;
489 DHCP_PROTOCOL
*Instance
;
494 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
495 return EFI_INVALID_PARAMETER
;
498 Instance
= NetAllocatePool (sizeof (*Instance
));
500 if (Instance
== NULL
) {
501 return EFI_OUT_OF_RESOURCES
;
504 DhcpSb
= DHCP_SERVICE_FROM_THIS (This
);
505 DhcpInitProtocol (DhcpSb
, Instance
);
508 // Install DHCP4 onto ChildHandle
510 Status
= gBS
->InstallMultipleProtocolInterfaces (
512 &gEfiDhcp4ProtocolGuid
,
513 &Instance
->Dhcp4Protocol
,
517 if (EFI_ERROR (Status
)) {
518 NetFreePool (Instance
);
522 Instance
->Handle
= *ChildHandle
;
525 // Open the Udp4 protocol BY_CHILD.
527 Status
= gBS
->OpenProtocol (
528 DhcpSb
->UdpIo
->UdpHandle
,
529 &gEfiUdp4ProtocolGuid
,
531 gDhcp4DriverBinding
.DriverBindingHandle
,
533 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
535 if (EFI_ERROR (Status
)) {
536 gBS
->UninstallMultipleProtocolInterfaces (
538 &gEfiDhcp4ProtocolGuid
,
539 &Instance
->Dhcp4Protocol
,
543 NetFreePool (Instance
);
547 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
549 NetListInsertTail (&DhcpSb
->Children
, &Instance
->Link
);
550 DhcpSb
->NumChildren
++;
552 NET_RESTORE_TPL (OldTpl
);
559 Destroys a child handle with a set of DHCP4 services.
561 @param This Protocol instance pointer.
562 @param ChildHandle Handle of the child to destroy
564 @retval EFI_SUCCES The DHCP4 service is removed from the child handle
565 @retval EFI_UNSUPPORTED The child handle does not support the DHCP4
567 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
568 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
569 its DHCP4 services are being used.
570 @retval other The child handle was not destroyed
575 Dhcp4ServiceBindingDestroyChild (
576 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
577 IN EFI_HANDLE ChildHandle
580 DHCP_SERVICE
*DhcpSb
;
581 DHCP_PROTOCOL
*Instance
;
582 EFI_DHCP4_PROTOCOL
*Dhcp
;
586 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
587 return EFI_INVALID_PARAMETER
;
591 // Retrieve the private context data structures
593 Status
= gBS
->OpenProtocol (
595 &gEfiDhcp4ProtocolGuid
,
597 gDhcp4DriverBinding
.DriverBindingHandle
,
599 EFI_OPEN_PROTOCOL_GET_PROTOCOL
602 if (EFI_ERROR (Status
)) {
603 return EFI_UNSUPPORTED
;
606 Instance
= DHCP_INSTANCE_FROM_THIS (Dhcp
);
607 DhcpSb
= DHCP_SERVICE_FROM_THIS (This
);
609 if (Instance
->Service
!= DhcpSb
) {
610 return EFI_INVALID_PARAMETER
;
614 // A child can be destoried more than once. For example,
615 // Dhcp4DriverBindingStop will destory all of its children.
616 // when caller driver is being stopped, it will destory the
617 // dhcp child it opens.
619 if (Instance
->InDestory
) {
623 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
624 Instance
->InDestory
= TRUE
;
627 // Close the Udp4 protocol.
630 DhcpSb
->UdpIo
->UdpHandle
,
631 &gEfiUdp4ProtocolGuid
,
632 gDhcp4DriverBinding
.DriverBindingHandle
,
637 // Uninstall the DHCP4 protocol first to enable a top down destruction.
639 Status
= gBS
->UninstallProtocolInterface (
641 &gEfiDhcp4ProtocolGuid
,
645 if (EFI_ERROR (Status
)) {
646 Instance
->InDestory
= FALSE
;
648 NET_RESTORE_TPL (OldTpl
);
652 if (DhcpSb
->ActiveChild
== Instance
) {
653 DhcpYieldControl (DhcpSb
);
656 NetListRemoveEntry (&Instance
->Link
);
657 DhcpSb
->NumChildren
--;
659 NET_RESTORE_TPL (OldTpl
);
661 NetFreePool (Instance
);