2 This code implements the IP4Config and NicIp4Config protocols.
4 Copyright (c) 2006 - 2010, 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<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"
16 #include "NicIp4Variable.h"
20 Get the NIC's configure information from the IP4 configure variable.
21 It will remove the invalid variable.
23 @param Instance The IP4 CONFIG instance.
25 @return NULL if no configure for the NIC in the variable, or it is invalid.
26 Otherwise the pointer to the NIC's IP configure parameter will be returned.
30 EfiNicIp4ConfigGetInfo (
31 IN IP4_CONFIG_INSTANCE
*Instance
34 NIC_IP4_CONFIG_INFO
*NicConfig
;
37 // Read the configuration parameter for this NIC from
40 NicConfig
= Ip4ConfigReadVariable (Instance
);
41 if (NicConfig
== NULL
) {
46 // Validate the configuration, if the configuration is invalid,
47 // remove it from the variable.
49 if (!Ip4ConfigIsValid (NicConfig
)) {
50 Ip4ConfigWriteVariable (Instance
, NULL
);
60 Set the IP configure parameters for this NIC.
62 If Reconfig is TRUE, the IP driver will be informed to discard current
63 auto configure parameter and restart the auto configuration process.
64 If current there is a pending auto configuration, EFI_ALREADY_STARTED is
65 returned. You can only change the configure setting when either
66 the configure has finished or not started yet. If NicConfig, the
67 NIC's configure parameter is removed from the variable.
69 @param Instance The IP4 CONFIG instance.
70 @param NicConfig The new NIC IP4 configure parameter.
71 @param Reconfig Inform the IP4 driver to restart the auto
74 @retval EFI_SUCCESS The configure parameter for this NIC was
76 @retval EFI_INVALID_PARAMETER This is NULL or the configure parameter is
78 @retval EFI_ALREADY_STARTED There is a pending auto configuration.
79 @retval EFI_NOT_FOUND No auto configure parameter is found.
84 EfiNicIp4ConfigSetInfo (
85 IN IP4_CONFIG_INSTANCE
*Instance
,
86 IN NIC_IP4_CONFIG_INFO
*NicConfig OPTIONAL
,
93 // Validate the parameters
95 if (Instance
== NULL
) {
96 return EFI_INVALID_PARAMETER
;
99 if ((NicConfig
!= NULL
) && (!Ip4ConfigIsValid (NicConfig
) ||
100 !NIC_ADDR_EQUAL (&NicConfig
->NicAddr
, &Instance
->NicAddr
))) {
101 return EFI_INVALID_PARAMETER
;
104 if (Instance
->State
== IP4_CONFIG_STATE_STARTED
) {
105 return EFI_ALREADY_STARTED
;
109 // Update the parameter in the configure variable
111 Status
= Ip4ConfigWriteVariable (Instance
, NicConfig
);
112 if (EFI_ERROR (Status
)) {
117 // Signal the IP4 to run the auto configuration again
119 if (Reconfig
&& (Instance
->ReconfigEvent
!= NULL
)) {
120 Status
= gBS
->SignalEvent (Instance
->ReconfigEvent
);
128 Callback function when DHCP process finished. It will save the
129 retrieved IP configure parameter from DHCP to the NVRam.
131 @param Event The callback event
132 @param Context Opaque context to the callback
139 Ip4ConfigOnDhcp4Complete (
144 IP4_CONFIG_INSTANCE
*Instance
;
145 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
146 EFI_IP4_IPCONFIG_DATA
*Ip4Config
;
153 Instance
= (IP4_CONFIG_INSTANCE
*) Context
;
154 ASSERT (Instance
->Dhcp4
!= NULL
);
156 Instance
->State
= IP4_CONFIG_STATE_CONFIGURED
;
157 Instance
->Result
= EFI_TIMEOUT
;
160 // Get the DHCP retrieved parameters
162 Status
= Instance
->Dhcp4
->GetModeData (Instance
->Dhcp4
, &Dhcp4Mode
);
164 if (EFI_ERROR (Status
)) {
168 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
170 // Save the new configuration retrieved by DHCP both in
171 // the instance and to NVRam. So, both the IP4 driver and
172 // other user can get that address.
176 if (Instance
->NicConfig
!= NULL
) {
177 ASSERT (Instance
->NicConfig
->Source
== IP4_CONFIG_SOURCE_DHCP
);
178 Perment
= Instance
->NicConfig
->Perment
;
179 FreePool (Instance
->NicConfig
);
182 Instance
->NicConfig
= AllocatePool (sizeof (NIC_IP4_CONFIG_INFO
) + 2* sizeof (EFI_IP4_ROUTE_TABLE
));
184 if (Instance
->NicConfig
== NULL
) {
185 Instance
->Result
= EFI_OUT_OF_RESOURCES
;
189 Instance
->NicConfig
->Ip4Info
.RouteTable
= (EFI_IP4_ROUTE_TABLE
*) (Instance
->NicConfig
+ 1);
191 CopyMem (&Instance
->NicConfig
->NicAddr
, &Instance
->NicAddr
, sizeof (Instance
->NicConfig
->NicAddr
));
192 Instance
->NicConfig
->Source
= IP4_CONFIG_SOURCE_DHCP
;
193 Instance
->NicConfig
->Perment
= Perment
;
195 Ip4Config
= &Instance
->NicConfig
->Ip4Info
;
196 Ip4Config
->StationAddress
= Dhcp4Mode
.ClientAddress
;
197 Ip4Config
->SubnetMask
= Dhcp4Mode
.SubnetMask
;
200 // Create a route for the connected network
202 Ip4Config
->RouteTableSize
= 1;
204 CopyMem (&Ip1
, &Dhcp4Mode
.ClientAddress
, sizeof (IP4_ADDR
));
205 CopyMem (&Ip2
, &Dhcp4Mode
.SubnetMask
, sizeof (IP4_ADDR
));
209 CopyMem (&Ip4Config
->RouteTable
[0].SubnetAddress
, &Subnet
, sizeof (EFI_IPv4_ADDRESS
));
210 CopyMem (&Ip4Config
->RouteTable
[0].SubnetMask
, &Dhcp4Mode
.SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
211 ZeroMem (&Ip4Config
->RouteTable
[0].GatewayAddress
, sizeof (EFI_IPv4_ADDRESS
));
214 // Create a route if there is a default router.
216 if (!EFI_IP4_EQUAL (&Dhcp4Mode
.RouterAddress
, &mZeroIp4Addr
)) {
217 Ip4Config
->RouteTableSize
= 2;
219 ZeroMem (&Ip4Config
->RouteTable
[1].SubnetAddress
, sizeof (EFI_IPv4_ADDRESS
));
220 ZeroMem (&Ip4Config
->RouteTable
[1].SubnetMask
, sizeof (EFI_IPv4_ADDRESS
));
221 CopyMem (&Ip4Config
->RouteTable
[1].GatewayAddress
, &Dhcp4Mode
.RouterAddress
, sizeof (EFI_IPv4_ADDRESS
));
224 Instance
->Result
= EFI_SUCCESS
;
227 // ignore the return status of EfiNicIp4ConfigSetInfo. Network
228 // stack can operate even that failed.
230 EfiNicIp4ConfigSetInfo (Instance
, Instance
->NicConfig
, FALSE
);
234 gBS
->SignalEvent (Instance
->DoneEvent
);
235 Ip4ConfigCleanDhcp4 (Instance
);
243 Starts running the configuration policy for the EFI IPv4 Protocol driver.
245 The Start() function is called to determine and to begin the platform
246 configuration policy by the EFI IPv4 Protocol driver. This determination may
247 be as simple as returning EFI_UNSUPPORTED if there is no EFI IPv4 Protocol
248 driver configuration policy. It may be as involved as loading some defaults
249 from nonvolatile storage, downloading dynamic data from a DHCP server, and
250 checking permissions with a site policy server.
251 Starting the configuration policy is just the beginning. It may finish almost
252 instantly or it may take several minutes before it fails to retrieve configuration
253 information from one or more servers. Once the policy is started, drivers
254 should use the DoneEvent parameter to determine when the configuration policy
255 has completed. EFI_IP4_CONFIG_PROTOCOL.GetData() must then be called to
256 determine if the configuration succeeded or failed.
257 Until the configuration completes successfully, EFI IPv4 Protocol driver instances
258 that are attempting to use default configurations must return EFI_NO_MAPPING.
259 Once the configuration is complete, the EFI IPv4 Configuration Protocol driver
260 signals DoneEvent. The configuration may need to be updated in the future,
261 however; in this case, the EFI IPv4 Configuration Protocol driver must signal
262 ReconfigEvent, and all EFI IPv4 Protocol driver instances that are using default
263 configurations must return EFI_NO_MAPPING until the configuration policy has
266 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
267 @param DoneEvent Event that will be signaled when the EFI IPv4
268 Protocol driver configuration policy completes
269 execution. This event must be of type EVT_NOTIFY_SIGNAL.
270 @param ReconfigEvent Event that will be signaled when the EFI IPv4
271 Protocol driver configuration needs to be updated.
272 This event must be of type EVT_NOTIFY_SIGNAL.
274 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
275 driver is now running.
276 @retval EFI_INVALID_PARAMETER One or more of the following parameters is NULL:
280 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
281 @retval EFI_ALREADY_STARTED The configuration policy for the EFI IPv4 Protocol
282 driver was already started.
283 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
284 @retval EFI_UNSUPPORTED This interface does not support the EFI IPv4 Protocol
285 driver configuration.
291 IN EFI_IP4_CONFIG_PROTOCOL
*This
,
292 IN EFI_EVENT DoneEvent
,
293 IN EFI_EVENT ReconfigEvent
296 IP4_CONFIG_INSTANCE
*Instance
;
297 EFI_DHCP4_PROTOCOL
*Dhcp4
;
298 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
299 EFI_DHCP4_PACKET_OPTION
*OptionList
[1];
300 IP4_CONFIG_DHCP4_OPTION ParaList
;
305 if ((This
== NULL
) || (DoneEvent
== NULL
) || (ReconfigEvent
== NULL
)) {
306 return EFI_INVALID_PARAMETER
;
309 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
311 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
313 if (Instance
->State
!= IP4_CONFIG_STATE_IDLE
) {
314 Status
= EFI_ALREADY_STARTED
;
319 Instance
->DoneEvent
= DoneEvent
;
320 Instance
->ReconfigEvent
= ReconfigEvent
;
322 Instance
->NicConfig
= EfiNicIp4ConfigGetInfo (Instance
);
324 if (Instance
->NicConfig
== NULL
) {
325 Source
= IP4_CONFIG_SOURCE_DHCP
;
327 Source
= Instance
->NicConfig
->Source
;
331 // If the source is static, the auto configuration is done.
334 if (Source
== IP4_CONFIG_SOURCE_STATIC
) {
335 Instance
->State
= IP4_CONFIG_STATE_CONFIGURED
;
336 Instance
->Result
= EFI_SUCCESS
;
338 gBS
->SignalEvent (Instance
->DoneEvent
);
339 Status
= EFI_SUCCESS
;
344 // Start the dhcp process
346 ASSERT ((Source
== IP4_CONFIG_SOURCE_DHCP
) && (Instance
->Dhcp4
== NULL
));
348 Status
= NetLibCreateServiceChild (
349 Instance
->Controller
,
351 &gEfiDhcp4ServiceBindingProtocolGuid
,
352 &Instance
->Dhcp4Handle
355 if (EFI_ERROR (Status
)) {
359 Status
= gBS
->OpenProtocol (
360 Instance
->Dhcp4Handle
,
361 &gEfiDhcp4ProtocolGuid
,
362 (VOID
**) &Instance
->Dhcp4
,
364 Instance
->Controller
,
365 EFI_OPEN_PROTOCOL_BY_DRIVER
368 if (EFI_ERROR (Status
)) {
373 // Check the current DHCP status, if the DHCP process has
374 // already finished, return now.
376 Dhcp4
= Instance
->Dhcp4
;
377 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
379 if (EFI_ERROR (Status
)) {
383 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
384 Ip4ConfigOnDhcp4Complete (NULL
, Instance
);
390 // Try to start the DHCP process. Use most of the current
391 // DHCP configuration to avoid problems if some DHCP client
392 // yields the control of this DHCP service to us.
394 ParaList
.Head
.OpCode
= DHCP_TAG_PARA_LIST
;
395 ParaList
.Head
.Length
= 2;
396 ParaList
.Head
.Data
[0] = DHCP_TAG_NETMASK
;
397 ParaList
.Route
= DHCP_TAG_ROUTER
;
398 OptionList
[0] = &ParaList
.Head
;
399 Dhcp4Mode
.ConfigData
.OptionCount
= 1;
400 Dhcp4Mode
.ConfigData
.OptionList
= OptionList
;
402 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4Mode
.ConfigData
);
404 if (EFI_ERROR (Status
)) {
409 // Start the DHCP process
411 Status
= gBS
->CreateEvent (
414 Ip4ConfigOnDhcp4Complete
,
416 &Instance
->Dhcp4Event
419 if (EFI_ERROR (Status
)) {
423 Status
= Dhcp4
->Start (Dhcp4
, Instance
->Dhcp4Event
);
425 if (EFI_ERROR (Status
)) {
429 Instance
->State
= IP4_CONFIG_STATE_STARTED
;
430 Instance
->Result
= EFI_NOT_READY
;
433 if (EFI_ERROR (Status
)) {
434 Ip4ConfigCleanConfig (Instance
);
438 gBS
->RestoreTPL (OldTpl
);
447 Stops running the configuration policy for the EFI IPv4 Protocol driver.
449 The Stop() function stops the configuration policy for the EFI IPv4 Protocol driver.
450 All configuration data will be lost after calling Stop().
452 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
454 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
455 driver has been stopped.
456 @retval EFI_INVALID_PARAMETER This is NULL.
457 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
458 driver was not started.
464 IN EFI_IP4_CONFIG_PROTOCOL
*This
467 IP4_CONFIG_INSTANCE
*Instance
;
472 return EFI_INVALID_PARAMETER
;
475 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
477 Status
= EFI_SUCCESS
;
478 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
480 if (Instance
->State
== IP4_CONFIG_STATE_IDLE
) {
481 Status
= EFI_NOT_STARTED
;
486 // Release all the configure parameters. Don't signal the user
487 // event. The user wants to abort the configuration, this isn't
488 // the configuration done or reconfiguration.
490 Ip4ConfigCleanConfig (Instance
);
493 gBS
->RestoreTPL (OldTpl
);
500 Returns the default configuration data (if any) for the EFI IPv4 Protocol driver.
502 The GetData() function returns the current configuration data for the EFI IPv4
503 Protocol driver after the configuration policy has completed.
505 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
506 @param ConfigDataSize On input, the size of the ConfigData buffer.
507 On output, the count of bytes that were written
508 into the ConfigData buffer.
509 @param ConfigData Pointer to the EFI IPv4 Configuration Protocol
510 driver configuration data structure.
511 Type EFI_IP4_IPCONFIG_DATA is defined in
512 "Related Definitions" below.
514 @retval EFI_SUCCESS The EFI IPv4 Protocol driver configuration has been returned.
515 @retval EFI_INVALID_PARAMETER This is NULL.
516 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
517 driver is not running.
518 @retval EFI_NOT_READY EFI IPv4 Protocol driver configuration is still running.
519 @retval EFI_ABORTED EFI IPv4 Protocol driver configuration could not complete.
520 Currently not implemented.
521 @retval EFI_BUFFER_TOO_SMALL *ConfigDataSize is smaller than the configuration
522 data buffer or ConfigData is NULL.
527 EfiIp4ConfigGetData (
528 IN EFI_IP4_CONFIG_PROTOCOL
*This
,
529 IN OUT UINTN
*ConfigDataSize
,
530 OUT EFI_IP4_IPCONFIG_DATA
*ConfigData OPTIONAL
533 IP4_CONFIG_INSTANCE
*Instance
;
534 NIC_IP4_CONFIG_INFO
*NicConfig
;
539 if ((This
== NULL
) || (ConfigDataSize
== NULL
)) {
540 return EFI_INVALID_PARAMETER
;
543 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
545 Status
= EFI_SUCCESS
;
546 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
548 if (Instance
->State
== IP4_CONFIG_STATE_IDLE
) {
549 Status
= EFI_NOT_STARTED
;
550 } else if (Instance
->State
== IP4_CONFIG_STATE_STARTED
) {
551 Status
= EFI_NOT_READY
;
554 if (EFI_ERROR (Status
)) {
559 // Copy the configure data if auto configuration succeeds.
561 Status
= Instance
->Result
;
563 if (Status
== EFI_SUCCESS
) {
564 ASSERT (Instance
->NicConfig
!= NULL
);
566 NicConfig
= Instance
->NicConfig
;
567 Len
= SIZEOF_IP4_CONFIG_INFO (&NicConfig
->Ip4Info
);
569 if ((*ConfigDataSize
< Len
) || (ConfigData
== NULL
)) {
570 Status
= EFI_BUFFER_TOO_SMALL
;
572 CopyMem (ConfigData
, &NicConfig
->Ip4Info
, Len
);
573 Ip4ConfigFixRouteTablePointer (ConfigData
);
576 *ConfigDataSize
= Len
;
580 gBS
->RestoreTPL (OldTpl
);
586 Release all the DHCP related resources.
588 @param This The IP4 configure instance
594 Ip4ConfigCleanDhcp4 (
595 IN IP4_CONFIG_INSTANCE
*This
598 if (This
->Dhcp4
!= NULL
) {
599 This
->Dhcp4
->Stop (This
->Dhcp4
);
603 &gEfiDhcp4ProtocolGuid
,
611 if (This
->Dhcp4Handle
!= NULL
) {
612 NetLibDestroyServiceChild (
615 &gEfiDhcp4ServiceBindingProtocolGuid
,
619 This
->Dhcp4Handle
= NULL
;
622 if (This
->Dhcp4Event
== NULL
) {
623 gBS
->CloseEvent (This
->Dhcp4Event
);
624 This
->Dhcp4Event
= NULL
;
630 Clean up all the configuration parameters.
632 @param Instance The IP4 configure instance
638 Ip4ConfigCleanConfig (
639 IN IP4_CONFIG_INSTANCE
*Instance
642 if (Instance
->NicConfig
!= NULL
) {
643 FreePool (Instance
->NicConfig
);
644 Instance
->NicConfig
= NULL
;
647 Instance
->State
= IP4_CONFIG_STATE_IDLE
;
648 Instance
->DoneEvent
= NULL
;
649 Instance
->ReconfigEvent
= NULL
;
651 Ip4ConfigCleanDhcp4 (Instance
);
654 EFI_IP4_CONFIG_PROTOCOL mIp4ConfigProtocolTemplate
= {