2 This code implements the IP4Config and NicIp4Config protocols.
4 Copyright (c) 2006 - 2009, 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<BR>
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.
15 #include "Ip4Config.h"
17 IP4_CONFIG_INSTANCE
*mIp4ConfigNicList
[MAX_IP4_CONFIG_IN_VARIABLE
];
21 Get the NIC's configure information from the IP4 configure variable.
22 It will remove the invalid variable.
24 @param NicAddr The NIC to check
26 @return NULL if no configure for the NIC in the variable, or it is invalid.
27 Otherwise the pointer to the NIC's IP configure parameter will be returned.
35 IP4_CONFIG_VARIABLE
*Variable
;
36 IP4_CONFIG_VARIABLE
*NewVariable
;
37 NIC_IP4_CONFIG_INFO
*Config
;
40 // Read the configuration parameter for this NicAddr from
43 Variable
= Ip4ConfigReadVariable ();
45 if (Variable
== NULL
) {
49 Config
= Ip4ConfigFindNicVariable (Variable
, NicAddr
);
57 // Validate the configuration, if the configuration is invalid,
58 // remove it from the variable.
60 if (!Ip4ConfigIsValid (Config
)) {
61 NewVariable
= Ip4ConfigModifyVariable (Variable
, &Config
->NicAddr
, NULL
);
62 Ip4ConfigWriteVariable (NewVariable
);
64 if (NewVariable
!= NULL
) {
65 FreePool (NewVariable
);
78 Get the configure parameter for this NIC.
80 @param Instance The IP4 CONFIG Instance.
81 @param ConfigLen The length of the NicConfig buffer.
82 @param NicConfig The buffer to receive the NIC's configure
85 @retval EFI_SUCCESS The configure parameter for this NIC was
86 obtained successfully .
87 @retval EFI_INVALID_PARAMETER This or ConfigLen is NULL.
88 @retval EFI_NOT_FOUND There is no configure parameter for the NIC in
90 @retval EFI_BUFFER_TOO_SMALL The ConfigLen is too small or the NicConfig is
96 EfiNicIp4ConfigGetInfo (
97 IN IP4_CONFIG_INSTANCE
*Instance
,
98 IN OUT UINTN
*ConfigLen
,
99 OUT NIC_IP4_CONFIG_INFO
*NicConfig
102 NIC_IP4_CONFIG_INFO
*Config
;
106 if ((Instance
== NULL
) || (ConfigLen
== NULL
)) {
107 return EFI_INVALID_PARAMETER
;
111 // Read the Nic's configuration parameter from variable
113 Config
= Ip4ConfigGetNicInfo (&Instance
->NicAddr
);
115 if (Config
== NULL
) {
116 return EFI_NOT_FOUND
;
120 // Copy the data to user's buffer
122 Len
= SIZEOF_NIC_IP4_CONFIG_INFO (Config
);
124 if ((*ConfigLen
< Len
) || (NicConfig
== NULL
)) {
125 Status
= EFI_BUFFER_TOO_SMALL
;
127 Status
= EFI_SUCCESS
;
128 CopyMem (NicConfig
, Config
, Len
);
129 Ip4ConfigFixRouteTablePointer (&NicConfig
->Ip4Info
);
140 Set the IP configure parameters for this NIC.
142 If Reconfig is TRUE, the IP driver will be informed to discard current
143 auto configure parameter and restart the auto configuration process.
144 If current there is a pending auto configuration, EFI_ALREADY_STARTED is
145 returned. You can only change the configure setting when either
146 the configure has finished or not started yet. If NicConfig, the
147 NIC's configure parameter is removed from the variable.
149 @param Instance The IP4 CONFIG instance.
150 @param NicConfig The new NIC IP4 configure parameter.
151 @param Reconfig Inform the IP4 driver to restart the auto
154 @retval EFI_SUCCESS The configure parameter for this NIC was
156 @retval EFI_INVALID_PARAMETER This is NULL or the configure parameter is
158 @retval EFI_ALREADY_STARTED There is a pending auto configuration.
159 @retval EFI_NOT_FOUND No auto configure parameter is found.
164 EfiNicIp4ConfigSetInfo (
165 IN IP4_CONFIG_INSTANCE
*Instance
,
166 IN NIC_IP4_CONFIG_INFO
*NicConfig OPTIONAL
,
170 IP4_CONFIG_VARIABLE
*Variable
;
171 IP4_CONFIG_VARIABLE
*NewVariable
;
175 // Validate the parameters
177 if (Instance
== NULL
) {
178 return EFI_INVALID_PARAMETER
;
181 if ((NicConfig
!= NULL
) && (!Ip4ConfigIsValid (NicConfig
) ||
182 !NIC_ADDR_EQUAL (&NicConfig
->NicAddr
, &Instance
->NicAddr
))) {
183 return EFI_INVALID_PARAMETER
;
186 if (Instance
->State
== IP4_CONFIG_STATE_STARTED
) {
187 return EFI_ALREADY_STARTED
;
191 // Update the parameter in the configure variable
193 Variable
= Ip4ConfigReadVariable ();
195 if ((Variable
== NULL
) && (NicConfig
== NULL
)) {
196 return EFI_NOT_FOUND
;
199 NewVariable
= Ip4ConfigModifyVariable (Variable
, &Instance
->NicAddr
, NicConfig
);
200 Status
= Ip4ConfigWriteVariable (NewVariable
);
202 if (NewVariable
!= NULL
) {
203 FreePool (NewVariable
);
207 // Variable is NULL when saving the first configure parameter
209 if (Variable
!= NULL
) {
213 if (EFI_ERROR (Status
)) {
218 // Signal the IP4 to run the auto configuration again
220 if (Reconfig
&& (Instance
->ReconfigEvent
!= NULL
)) {
221 Status
= gBS
->SignalEvent (Instance
->ReconfigEvent
);
229 Callback function when DHCP process finished. It will save the
230 retrieved IP configure parameter from DHCP to the NVRam.
232 @param Event The callback event
233 @param Context Opaque context to the callback
240 Ip4ConfigOnDhcp4Complete (
245 IP4_CONFIG_INSTANCE
*Instance
;
246 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
247 EFI_IP4_IPCONFIG_DATA
*Ip4Config
;
254 Instance
= (IP4_CONFIG_INSTANCE
*) Context
;
255 ASSERT (Instance
->Dhcp4
!= NULL
);
257 Instance
->State
= IP4_CONFIG_STATE_CONFIGURED
;
258 Instance
->Result
= EFI_TIMEOUT
;
261 // Get the DHCP retrieved parameters
263 Status
= Instance
->Dhcp4
->GetModeData (Instance
->Dhcp4
, &Dhcp4Mode
);
265 if (EFI_ERROR (Status
)) {
269 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
271 // Save the new configuration retrieved by DHCP both in
272 // the instance and to NVRam. So, both the IP4 driver and
273 // other user can get that address.
277 if (Instance
->NicConfig
!= NULL
) {
278 ASSERT (Instance
->NicConfig
->Source
== IP4_CONFIG_SOURCE_DHCP
);
279 Perment
= Instance
->NicConfig
->Perment
;
280 FreePool (Instance
->NicConfig
);
283 Instance
->NicConfig
= AllocatePool (sizeof (NIC_IP4_CONFIG_INFO
) + 2* sizeof (EFI_IP4_ROUTE_TABLE
));
285 if (Instance
->NicConfig
== NULL
) {
286 Instance
->Result
= EFI_OUT_OF_RESOURCES
;
290 Instance
->NicConfig
->Ip4Info
.RouteTable
= (EFI_IP4_ROUTE_TABLE
*) (Instance
->NicConfig
+ 1);
292 CopyMem (&Instance
->NicConfig
->NicAddr
, &Instance
->NicAddr
, sizeof (Instance
->NicConfig
->NicAddr
));
293 Instance
->NicConfig
->Source
= IP4_CONFIG_SOURCE_DHCP
;
294 Instance
->NicConfig
->Perment
= Perment
;
296 Ip4Config
= &Instance
->NicConfig
->Ip4Info
;
297 Ip4Config
->StationAddress
= Dhcp4Mode
.ClientAddress
;
298 Ip4Config
->SubnetMask
= Dhcp4Mode
.SubnetMask
;
301 // Create a route for the connected network
303 Ip4Config
->RouteTableSize
= 1;
305 CopyMem (&Ip1
, &Dhcp4Mode
.ClientAddress
, sizeof (IP4_ADDR
));
306 CopyMem (&Ip2
, &Dhcp4Mode
.SubnetMask
, sizeof (IP4_ADDR
));
310 CopyMem (&Ip4Config
->RouteTable
[0].SubnetAddress
, &Subnet
, sizeof (EFI_IPv4_ADDRESS
));
311 CopyMem (&Ip4Config
->RouteTable
[0].SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
312 ZeroMem (&Ip4Config
->RouteTable
[0].GatewayAddress
, sizeof (EFI_IPv4_ADDRESS
));
315 // Create a route if there is a default router.
317 if (!EFI_IP4_EQUAL (&Dhcp4Mode
.RouterAddress
, &mZeroIp4Addr
)) {
318 Ip4Config
->RouteTableSize
= 2;
320 ZeroMem (&Ip4Config
->RouteTable
[1].SubnetAddress
, sizeof (EFI_IPv4_ADDRESS
));
321 ZeroMem (&Ip4Config
->RouteTable
[1].SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
322 CopyMem (&Ip4Config
->RouteTable
[1].GatewayAddress
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
325 Instance
->Result
= EFI_SUCCESS
;
328 // ignore the return status of EfiNicIp4ConfigSetInfo. Network
329 // stack can operate even that failed.
331 EfiNicIp4ConfigSetInfo (Instance
, Instance
->NicConfig
, FALSE
);
335 gBS
->SignalEvent (Instance
->DoneEvent
);
336 Ip4ConfigCleanDhcp4 (Instance
);
344 Starts running the configuration policy for the EFI IPv4 Protocol driver.
346 The Start() function is called to determine and to begin the platform
347 configuration policy by the EFI IPv4 Protocol driver. This determination may
348 be as simple as returning EFI_UNSUPPORTED if there is no EFI IPv4 Protocol
349 driver configuration policy. It may be as involved as loading some defaults
350 from nonvolatile storage, downloading dynamic data from a DHCP server, and
351 checking permissions with a site policy server.
352 Starting the configuration policy is just the beginning. It may finish almost
353 instantly or it may take several minutes before it fails to retrieve configuration
354 information from one or more servers. Once the policy is started, drivers
355 should use the DoneEvent parameter to determine when the configuration policy
356 has completed. EFI_IP4_CONFIG_PROTOCOL.GetData() must then be called to
357 determine if the configuration succeeded or failed.
358 Until the configuration completes successfully, EFI IPv4 Protocol driver instances
359 that are attempting to use default configurations must return EFI_NO_MAPPING.
360 Once the configuration is complete, the EFI IPv4 Configuration Protocol driver
361 signals DoneEvent. The configuration may need to be updated in the future,
362 however; in this case, the EFI IPv4 Configuration Protocol driver must signal
363 ReconfigEvent, and all EFI IPv4 Protocol driver instances that are using default
364 configurations must return EFI_NO_MAPPING until the configuration policy has
367 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
368 @param DoneEvent Event that will be signaled when the EFI IPv4
369 Protocol driver configuration policy completes
370 execution. This event must be of type EVT_NOTIFY_SIGNAL.
371 @param ReconfigEvent Event that will be signaled when the EFI IPv4
372 Protocol driver configuration needs to be updated.
373 This event must be of type EVT_NOTIFY_SIGNAL.
375 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
376 driver is now running.
377 @retval EFI_INVALID_PARAMETER One or more of the following parameters is NULL:
381 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
382 @retval EFI_ALREADY_STARTED The configuration policy for the EFI IPv4 Protocol
383 driver was already started.
384 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
385 @retval EFI_UNSUPPORTED This interface does not support the EFI IPv4 Protocol
386 driver configuration.
392 IN EFI_IP4_CONFIG_PROTOCOL
*This
,
393 IN EFI_EVENT DoneEvent
,
394 IN EFI_EVENT ReconfigEvent
397 IP4_CONFIG_INSTANCE
*Instance
;
398 EFI_DHCP4_PROTOCOL
*Dhcp4
;
399 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
400 EFI_DHCP4_PACKET_OPTION
*OptionList
[1];
401 IP4_CONFIG_DHCP4_OPTION ParaList
;
406 if ((This
== NULL
) || (DoneEvent
== NULL
) || (ReconfigEvent
== NULL
)) {
407 return EFI_INVALID_PARAMETER
;
410 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
412 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
414 if (Instance
->State
!= IP4_CONFIG_STATE_IDLE
) {
415 Status
= EFI_ALREADY_STARTED
;
420 Instance
->DoneEvent
= DoneEvent
;
421 Instance
->ReconfigEvent
= ReconfigEvent
;
423 Instance
->NicConfig
= Ip4ConfigGetNicInfo (&Instance
->NicAddr
);
425 if (Instance
->NicConfig
== NULL
) {
426 Source
= IP4_CONFIG_SOURCE_DHCP
;
428 Source
= Instance
->NicConfig
->Source
;
432 // If the source is static, the auto configuration is done.
435 if (Source
== IP4_CONFIG_SOURCE_STATIC
) {
436 Instance
->State
= IP4_CONFIG_STATE_CONFIGURED
;
437 Instance
->Result
= EFI_SUCCESS
;
439 gBS
->SignalEvent (Instance
->DoneEvent
);
440 Status
= EFI_SUCCESS
;
445 // Start the dhcp process
447 ASSERT ((Source
== IP4_CONFIG_SOURCE_DHCP
) && (Instance
->Dhcp4
== NULL
));
449 Status
= NetLibCreateServiceChild (
450 Instance
->Controller
,
452 &gEfiDhcp4ServiceBindingProtocolGuid
,
453 &Instance
->Dhcp4Handle
456 if (EFI_ERROR (Status
)) {
460 Status
= gBS
->OpenProtocol (
461 Instance
->Dhcp4Handle
,
462 &gEfiDhcp4ProtocolGuid
,
463 (VOID
**) &Instance
->Dhcp4
,
465 Instance
->Controller
,
466 EFI_OPEN_PROTOCOL_BY_DRIVER
469 if (EFI_ERROR (Status
)) {
474 // Check the current DHCP status, if the DHCP process has
475 // already finished, return now.
477 Dhcp4
= Instance
->Dhcp4
;
478 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
480 if (EFI_ERROR (Status
)) {
484 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
485 Ip4ConfigOnDhcp4Complete (NULL
, Instance
);
491 // Try to start the DHCP process. Use most of the current
492 // DHCP configuration to avoid problems if some DHCP client
493 // yields the control of this DHCP service to us.
495 ParaList
.Head
.OpCode
= DHCP_TAG_PARA_LIST
;
496 ParaList
.Head
.Length
= 2;
497 ParaList
.Head
.Data
[0] = DHCP_TAG_NETMASK
;
498 ParaList
.Route
= DHCP_TAG_ROUTER
;
499 OptionList
[0] = &ParaList
.Head
;
500 Dhcp4Mode
.ConfigData
.OptionCount
= 1;
501 Dhcp4Mode
.ConfigData
.OptionList
= OptionList
;
503 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4Mode
.ConfigData
);
505 if (EFI_ERROR (Status
)) {
510 // Start the DHCP process
512 Status
= gBS
->CreateEvent (
515 Ip4ConfigOnDhcp4Complete
,
517 &Instance
->Dhcp4Event
520 if (EFI_ERROR (Status
)) {
524 Status
= Dhcp4
->Start (Dhcp4
, Instance
->Dhcp4Event
);
526 if (EFI_ERROR (Status
)) {
530 Instance
->State
= IP4_CONFIG_STATE_STARTED
;
531 Instance
->Result
= EFI_NOT_READY
;
534 if (EFI_ERROR (Status
)) {
535 Ip4ConfigCleanConfig (Instance
);
539 gBS
->RestoreTPL (OldTpl
);
548 Stops running the configuration policy for the EFI IPv4 Protocol driver.
550 The Stop() function stops the configuration policy for the EFI IPv4 Protocol driver.
551 All configuration data will be lost after calling Stop().
553 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
555 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
556 driver has been stopped.
557 @retval EFI_INVALID_PARAMETER This is NULL.
558 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
559 driver was not started.
565 IN EFI_IP4_CONFIG_PROTOCOL
*This
568 IP4_CONFIG_INSTANCE
*Instance
;
573 return EFI_INVALID_PARAMETER
;
576 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
578 Status
= EFI_SUCCESS
;
579 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
581 if (Instance
->State
== IP4_CONFIG_STATE_IDLE
) {
582 Status
= EFI_NOT_STARTED
;
587 // Release all the configure parameters. Don't signal the user
588 // event. The user wants to abort the configuration, this isn't
589 // the configuration done or reconfiguration.
591 Ip4ConfigCleanConfig (Instance
);
594 gBS
->RestoreTPL (OldTpl
);
601 Returns the default configuration data (if any) for the EFI IPv4 Protocol driver.
603 The GetData() function returns the current configuration data for the EFI IPv4
604 Protocol driver after the configuration policy has completed.
606 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
607 @param ConfigDataSize On input, the size of the ConfigData buffer.
608 On output, the count of bytes that were written
609 into the ConfigData buffer.
610 @param ConfigData Pointer to the EFI IPv4 Configuration Protocol
611 driver configuration data structure.
612 Type EFI_IP4_IPCONFIG_DATA is defined in
613 "Related Definitions" below.
615 @retval EFI_SUCCESS The EFI IPv4 Protocol driver configuration has been returned.
616 @retval EFI_INVALID_PARAMETER This is NULL.
617 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
618 driver is not running.
619 @retval EFI_NOT_READY EFI IPv4 Protocol driver configuration is still running.
620 @retval EFI_ABORTED EFI IPv4 Protocol driver configuration could not complete.
621 Currently not implemented.
622 @retval EFI_BUFFER_TOO_SMALL *ConfigDataSize is smaller than the configuration
623 data buffer or ConfigData is NULL.
628 EfiIp4ConfigGetData (
629 IN EFI_IP4_CONFIG_PROTOCOL
*This
,
630 IN OUT UINTN
*ConfigDataSize
,
631 OUT EFI_IP4_IPCONFIG_DATA
*ConfigData OPTIONAL
634 IP4_CONFIG_INSTANCE
*Instance
;
635 NIC_IP4_CONFIG_INFO
*NicConfig
;
640 if ((This
== NULL
) || (ConfigDataSize
== NULL
)) {
641 return EFI_INVALID_PARAMETER
;
644 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
646 Status
= EFI_SUCCESS
;
647 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
649 if (Instance
->State
== IP4_CONFIG_STATE_IDLE
) {
650 Status
= EFI_NOT_STARTED
;
651 } else if (Instance
->State
== IP4_CONFIG_STATE_STARTED
) {
652 Status
= EFI_NOT_READY
;
655 if (EFI_ERROR (Status
)) {
660 // Copy the configure data if auto configuration succeeds.
662 Status
= Instance
->Result
;
664 if (Status
== EFI_SUCCESS
) {
665 ASSERT (Instance
->NicConfig
!= NULL
);
667 NicConfig
= Instance
->NicConfig
;
668 Len
= SIZEOF_IP4_CONFIG_INFO (&NicConfig
->Ip4Info
);
670 if ((*ConfigDataSize
< Len
) || (ConfigData
== NULL
)) {
671 Status
= EFI_BUFFER_TOO_SMALL
;
673 CopyMem (ConfigData
, &NicConfig
->Ip4Info
, Len
);
674 Ip4ConfigFixRouteTablePointer (ConfigData
);
677 *ConfigDataSize
= Len
;
681 gBS
->RestoreTPL (OldTpl
);
687 Release all the DHCP related resources.
689 @param This The IP4 configure instance
695 Ip4ConfigCleanDhcp4 (
696 IN IP4_CONFIG_INSTANCE
*This
699 if (This
->Dhcp4
!= NULL
) {
700 This
->Dhcp4
->Stop (This
->Dhcp4
);
704 &gEfiDhcp4ProtocolGuid
,
712 if (This
->Dhcp4Handle
!= NULL
) {
713 NetLibDestroyServiceChild (
716 &gEfiDhcp4ServiceBindingProtocolGuid
,
720 This
->Dhcp4Handle
= NULL
;
723 if (This
->Dhcp4Event
== NULL
) {
724 gBS
->CloseEvent (This
->Dhcp4Event
);
725 This
->Dhcp4Event
= NULL
;
731 Clean up all the configuration parameters.
733 @param Instance The IP4 configure instance
739 Ip4ConfigCleanConfig (
740 IN IP4_CONFIG_INSTANCE
*Instance
743 if (Instance
->NicConfig
!= NULL
) {
744 FreePool (Instance
->NicConfig
);
745 Instance
->NicConfig
= NULL
;
748 Instance
->State
= IP4_CONFIG_STATE_IDLE
;
749 Instance
->DoneEvent
= NULL
;
750 Instance
->ReconfigEvent
= NULL
;
752 Ip4ConfigCleanDhcp4 (Instance
);
755 EFI_IP4_CONFIG_PROTOCOL mIp4ConfigProtocolTemplate
= {