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
39 //@MT: EFI_DRIVER_ENTRY_POINT (Dhcp4DriverEntryPoint)
43 Dhcp4DriverEntryPoint (
44 IN EFI_HANDLE ImageHandle
,
45 IN EFI_SYSTEM_TABLE
*SystemTable
51 Entry point of the DHCP driver to install various protocols.
55 ImageHandle - The driver's image handle
56 SystemTable - The system table
60 EFI_SUCCESS - All the related protocols are installed.
61 Others - Failed to install the protocols.
65 return NetLibInstallAllDriverProtocols (
78 Test to see if DHCP driver supports the ControllerHandle.
80 @param This Protocol instance pointer.
81 @param ControllerHandle Handle of device to test
82 @param RemainingDevicePath Optional parameter use to pick a specific child
85 @retval EFI_SUCCES This driver supports this device
86 @retval other This driver does not support this device
91 Dhcp4DriverBindingSupported (
92 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
93 IN EFI_HANDLE ControllerHandle
,
94 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
99 Status
= gBS
->OpenProtocol (
101 &gEfiUdp4ServiceBindingProtocolGuid
,
103 This
->DriverBindingHandle
,
105 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
114 Configure the default UDP child to receive all the DHCP traffics
115 on this network interface.
117 @param UdpIo The UDP IO port to configure
118 @param Context The context to the function
120 @retval EFI_SUCCESS The UDP IO port is successfully configured.
121 @retval Others Failed to configure the UDP child.
126 IN UDP_IO_PORT
*UdpIo
,
130 EFI_UDP4_CONFIG_DATA UdpConfigData
;
132 UdpConfigData
.AcceptBroadcast
= TRUE
;
133 UdpConfigData
.AcceptPromiscuous
= FALSE
;
134 UdpConfigData
.AcceptAnyPort
= FALSE
;
135 UdpConfigData
.AllowDuplicatePort
= TRUE
;
136 UdpConfigData
.TypeOfService
= 0;
137 UdpConfigData
.TimeToLive
= 64;
138 UdpConfigData
.DoNotFragment
= FALSE
;
139 UdpConfigData
.ReceiveTimeout
= 0;
140 UdpConfigData
.TransmitTimeout
= 0;
142 UdpConfigData
.UseDefaultAddress
= FALSE
;
143 UdpConfigData
.StationPort
= DHCP_CLIENT_PORT
;
144 UdpConfigData
.RemotePort
= DHCP_SERVER_PORT
;
146 NetZeroMem (&UdpConfigData
.StationAddress
, sizeof (EFI_IPv4_ADDRESS
));
147 NetZeroMem (&UdpConfigData
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
148 NetZeroMem (&UdpConfigData
.RemoteAddress
, sizeof (EFI_IPv4_ADDRESS
));
150 return UdpIo
->Udp
->Configure (UdpIo
->Udp
, &UdpConfigData
);;
156 Destory the DHCP service. The Dhcp4 service may be partly initialized,
157 or partly destoried. If a resource is destoried, it is marked as so in
158 case the destory failed and being called again later.
160 @param DhcpSb The DHCP service instance to destory.
162 @retval EFI_SUCCESS The DHCP service is successfully closed.
167 IN DHCP_SERVICE
*DhcpSb
170 DhcpCleanLease (DhcpSb
);
172 if (DhcpSb
->UdpIo
!= NULL
) {
173 UdpIoFreePort (DhcpSb
->UdpIo
);
174 DhcpSb
->UdpIo
= NULL
;
177 if (DhcpSb
->Timer
!= NULL
) {
178 gBS
->SetTimer (DhcpSb
->Timer
, TimerCancel
, 0);
179 gBS
->CloseEvent (DhcpSb
->Timer
);
181 DhcpSb
->Timer
= NULL
;
190 Create a new DHCP service binding instance for the controller.
192 @param Controller The controller to install DHCP service binding
194 @param ImageHandle The driver's image handle
195 @param Service The variable to receive the created DHCP service
198 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource .
199 @retval EFI_SUCCESS The DHCP service instance is created.
204 IN EFI_HANDLE Controller
,
205 IN EFI_HANDLE ImageHandle
,
206 OUT DHCP_SERVICE
**Service
209 DHCP_SERVICE
*DhcpSb
;
213 DhcpSb
= NetAllocateZeroPool (sizeof (DHCP_SERVICE
));
215 if (DhcpSb
== NULL
) {
216 return EFI_OUT_OF_RESOURCES
;
219 DhcpSb
->Signature
= DHCP_SERVICE_SIGNATURE
;
220 DhcpSb
->ServiceBinding
= mDhcp4ServiceBindingTemplete
;
221 DhcpSb
->ServiceState
= DHCP_UNCONFIGED
;
222 DhcpSb
->InDestory
= FALSE
;
223 DhcpSb
->Controller
= Controller
;
224 DhcpSb
->Image
= ImageHandle
;
225 NetListInit (&DhcpSb
->Children
);
226 DhcpSb
->DhcpState
= Dhcp4Stopped
;
227 DhcpSb
->Xid
= NET_RANDOM (NetRandomInitSeed ());
230 // Create various resources, UdpIo, Timer, and get Mac address
232 Status
= gBS
->CreateEvent (
233 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
240 if (EFI_ERROR (Status
)) {
244 DhcpSb
->UdpIo
= UdpIoCreatePort (Controller
, ImageHandle
, DhcpConfigUdpIo
, NULL
);
246 if (DhcpSb
->UdpIo
== NULL
) {
247 Status
= EFI_OUT_OF_RESOURCES
;
251 DhcpSb
->HwLen
= (UINT8
) DhcpSb
->UdpIo
->SnpMode
.HwAddressSize
;
252 DhcpSb
->HwType
= DhcpSb
->UdpIo
->SnpMode
.IfType
;
253 CopyMem (&DhcpSb
->Mac
, &DhcpSb
->UdpIo
->SnpMode
.CurrentAddress
, sizeof (EFI_MAC_ADDRESS
));
259 Dhcp4CloseService (DhcpSb
);
260 NetFreePool (DhcpSb
);
267 Start this driver on ControllerHandle.
269 @param This Protocol instance pointer.
270 @param ControllerHandle Handle of device to bind driver to
271 @param RemainingDevicePath Optional parameter use to pick a specific child
274 @retval EFI_SUCCES This driver is added to ControllerHandle
275 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle
276 @retval other This driver does not support this device
281 Dhcp4DriverBindingStart (
282 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
283 IN EFI_HANDLE ControllerHandle
,
284 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
287 DHCP_SERVICE
*DhcpSb
;
291 // First: test for the DHCP4 Protocol
293 Status
= gBS
->OpenProtocol (
295 &gEfiDhcp4ServiceBindingProtocolGuid
,
297 This
->DriverBindingHandle
,
299 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
302 if (Status
== EFI_SUCCESS
) {
303 return EFI_ALREADY_STARTED
;
306 Status
= Dhcp4CreateService (ControllerHandle
, This
->DriverBindingHandle
, &DhcpSb
);
308 if (EFI_ERROR (Status
)) {
312 Status
= gBS
->SetTimer (DhcpSb
->Timer
, TimerPeriodic
, TICKS_PER_SECOND
);
314 if (EFI_ERROR (Status
)) {
319 // Install the Dhcp4ServiceBinding Protocol onto ControlerHandle
321 Status
= gBS
->InstallMultipleProtocolInterfaces (
323 &gEfiDhcp4ServiceBindingProtocolGuid
,
324 &DhcpSb
->ServiceBinding
,
328 if (EFI_ERROR (Status
)) {
335 Dhcp4CloseService (DhcpSb
);
336 NetFreePool (DhcpSb
);
342 Stop this driver on ControllerHandle.
344 @param This Protocol instance pointer.
345 @param ControllerHandle Handle of device to stop driver on
346 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number
347 of children is zero stop the entire bus driver.
348 @param ChildHandleBuffer List of Child Handles to Stop.
350 @retval EFI_SUCCES This driver is removed ControllerHandle
351 @retval other This driver was not removed from this device
356 Dhcp4DriverBindingStop (
357 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
358 IN EFI_HANDLE ControllerHandle
,
359 IN UINTN NumberOfChildren
,
360 IN EFI_HANDLE
*ChildHandleBuffer
363 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
364 DHCP_SERVICE
*DhcpSb
;
365 DHCP_PROTOCOL
*Instance
;
366 EFI_HANDLE NicHandle
;
371 // DHCP driver opens UDP child, So, the ControllerHandle is the
372 // UDP child handle. locate the Nic handle first.
374 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiUdp4ProtocolGuid
);
376 if (NicHandle
== NULL
) {
380 Status
= gBS
->OpenProtocol (
382 &gEfiDhcp4ServiceBindingProtocolGuid
,
383 (VOID
**) &ServiceBinding
,
384 This
->DriverBindingHandle
,
386 EFI_OPEN_PROTOCOL_GET_PROTOCOL
389 if (EFI_ERROR (Status
)) {
390 return EFI_DEVICE_ERROR
;
393 DhcpSb
= DHCP_SERVICE_FROM_THIS (ServiceBinding
);
395 if (DhcpSb
->InDestory
) {
399 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
400 DhcpSb
->InDestory
= TRUE
;
403 // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild
404 // may cause other child to be deleted.
406 while (!NetListIsEmpty (&DhcpSb
->Children
)) {
407 Instance
= NET_LIST_HEAD (&DhcpSb
->Children
, DHCP_PROTOCOL
, Link
);
408 Dhcp4ServiceBindingDestroyChild (ServiceBinding
, Instance
->Handle
);
411 if (DhcpSb
->NumChildren
!= 0) {
412 Status
= EFI_DEVICE_ERROR
;
416 DhcpSb
->ServiceState
= DHCP_DESTORY
;
418 Status
= gBS
->UninstallProtocolInterface (
420 &gEfiDhcp4ServiceBindingProtocolGuid
,
424 if (EFI_ERROR (Status
)) {
428 Dhcp4CloseService (DhcpSb
);
429 NET_RESTORE_TPL (OldTpl
);
431 NetFreePool (DhcpSb
);
435 DhcpSb
->InDestory
= FALSE
;
436 NET_RESTORE_TPL (OldTpl
);
442 Initialize a new DHCP child
444 @param DhcpSb The dhcp service instance
445 @param Instance The dhcp instance to initialize
452 IN DHCP_SERVICE
*DhcpSb
,
453 IN DHCP_PROTOCOL
*Instance
456 Instance
->Signature
= DHCP_PROTOCOL_SIGNATURE
;
457 CopyMem (&Instance
->Dhcp4Protocol
, &mDhcp4ProtocolTemplate
, sizeof (EFI_DHCP4_PROTOCOL
));
458 NetListInit (&Instance
->Link
);
459 Instance
->Handle
= NULL
;
460 Instance
->Service
= DhcpSb
;
461 Instance
->InDestory
= FALSE
;
462 Instance
->CompletionEvent
= NULL
;
463 Instance
->RenewRebindEvent
= NULL
;
464 Instance
->Token
= NULL
;
469 Creates a child handle with a set of DHCP4 services.
471 @param This Protocol instance pointer.
472 @param ChildHandle Pointer to the handle of the child to create. If
473 it is NULL, then a new handle is created. If it
474 is not NULL, then the DHCP4 services are added to
475 the existing child handle.
477 @retval EFI_SUCCES The child handle was created with the DHCP4
479 @retval EFI_OUT_OF_RESOURCES There are not enough resources to create the child
480 @retval other The child handle was not created
485 Dhcp4ServiceBindingCreateChild (
486 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
487 IN EFI_HANDLE
*ChildHandle
490 DHCP_SERVICE
*DhcpSb
;
491 DHCP_PROTOCOL
*Instance
;
496 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
497 return EFI_INVALID_PARAMETER
;
500 Instance
= NetAllocatePool (sizeof (*Instance
));
502 if (Instance
== NULL
) {
503 return EFI_OUT_OF_RESOURCES
;
506 DhcpSb
= DHCP_SERVICE_FROM_THIS (This
);
507 DhcpInitProtocol (DhcpSb
, Instance
);
510 // Install DHCP4 onto ChildHandle
512 Status
= gBS
->InstallMultipleProtocolInterfaces (
514 &gEfiDhcp4ProtocolGuid
,
515 &Instance
->Dhcp4Protocol
,
519 if (EFI_ERROR (Status
)) {
520 NetFreePool (Instance
);
524 Instance
->Handle
= *ChildHandle
;
527 // Open the Udp4 protocol BY_CHILD.
529 Status
= gBS
->OpenProtocol (
530 DhcpSb
->UdpIo
->UdpHandle
,
531 &gEfiUdp4ProtocolGuid
,
533 gDhcp4DriverBinding
.DriverBindingHandle
,
535 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
537 if (EFI_ERROR (Status
)) {
538 gBS
->UninstallMultipleProtocolInterfaces (
540 &gEfiDhcp4ProtocolGuid
,
541 &Instance
->Dhcp4Protocol
,
545 NetFreePool (Instance
);
549 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
551 NetListInsertTail (&DhcpSb
->Children
, &Instance
->Link
);
552 DhcpSb
->NumChildren
++;
554 NET_RESTORE_TPL (OldTpl
);
561 Destroys a child handle with a set of DHCP4 services.
563 @param This Protocol instance pointer.
564 @param ChildHandle Handle of the child to destroy
566 @retval EFI_SUCCES The DHCP4 service is removed from the child handle
567 @retval EFI_UNSUPPORTED The child handle does not support the DHCP4
569 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.
570 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
571 its DHCP4 services are being used.
572 @retval other The child handle was not destroyed
577 Dhcp4ServiceBindingDestroyChild (
578 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
579 IN EFI_HANDLE ChildHandle
582 DHCP_SERVICE
*DhcpSb
;
583 DHCP_PROTOCOL
*Instance
;
584 EFI_DHCP4_PROTOCOL
*Dhcp
;
588 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
589 return EFI_INVALID_PARAMETER
;
593 // Retrieve the private context data structures
595 Status
= gBS
->OpenProtocol (
597 &gEfiDhcp4ProtocolGuid
,
599 gDhcp4DriverBinding
.DriverBindingHandle
,
601 EFI_OPEN_PROTOCOL_GET_PROTOCOL
604 if (EFI_ERROR (Status
)) {
605 return EFI_UNSUPPORTED
;
608 Instance
= DHCP_INSTANCE_FROM_THIS (Dhcp
);
609 DhcpSb
= DHCP_SERVICE_FROM_THIS (This
);
611 if (Instance
->Service
!= DhcpSb
) {
612 return EFI_INVALID_PARAMETER
;
616 // A child can be destoried more than once. For example,
617 // Dhcp4DriverBindingStop will destory all of its children.
618 // when caller driver is being stopped, it will destory the
619 // dhcp child it opens.
621 if (Instance
->InDestory
) {
625 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
626 Instance
->InDestory
= TRUE
;
629 // Close the Udp4 protocol.
632 DhcpSb
->UdpIo
->UdpHandle
,
633 &gEfiUdp4ProtocolGuid
,
634 gDhcp4DriverBinding
.DriverBindingHandle
,
639 // Uninstall the DHCP4 protocol first to enable a top down destruction.
641 Status
= gBS
->UninstallProtocolInterface (
643 &gEfiDhcp4ProtocolGuid
,
647 if (EFI_ERROR (Status
)) {
648 Instance
->InDestory
= FALSE
;
650 NET_RESTORE_TPL (OldTpl
);
654 if (DhcpSb
->ActiveChild
== Instance
) {
655 DhcpYieldControl (DhcpSb
);
658 NetListRemoveEntry (&Instance
->Link
);
659 DhcpSb
->NumChildren
--;
661 NET_RESTORE_TPL (OldTpl
);
663 NetFreePool (Instance
);