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.
18 This code implements the IP4Config and NicIp4Config protocols.
23 #include "Ip4Config.h"
25 IP4_CONFIG_INSTANCE
*mIp4ConfigNicList
[MAX_IP4_CONFIG_IN_VARIABLE
];
29 Ip4ConfigOnDhcp4Complete (
36 Return the name and MAC address for the NIC. The Name, if not NULL,
37 has at least IP4_NIC_NAME_LENGTH bytes.
39 @param This The NIC IP4 CONFIG protocol
40 @param Name The buffer to return the name
41 @param NicAddr The buffer to return the MAC addr
43 @retval EFI_INVALID_PARAMETER This is NULL
44 @retval EFI_SUCCESS The name or address of the NIC are returned.
50 EfiNicIp4ConfigGetName (
51 IN EFI_NIC_IP4_CONFIG_PROTOCOL
*This
,
52 IN UINT16
*Name
, OPTIONAL
53 IN NIC_ADDR
*NicAddr OPTIONAL
56 IP4_CONFIG_INSTANCE
*Instance
;
59 return EFI_INVALID_PARAMETER
;
62 Instance
= IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This
);
65 NetCopyMem (Name
, Instance
->NicName
, IP4_NIC_NAME_LENGTH
);
68 if (NicAddr
!= NULL
) {
69 CopyMem (NicAddr
, &Instance
->NicAddr
, sizeof (NIC_ADDR
));
77 Get the NIC's configure information from the IP4 configure variable.
78 It will remove the invalid variable.
80 @param NicAddr The NIC to check
82 @return NULL if no configure for the NIC in the variable, or it is invalid.
83 @return Otherwise the NIC's IP configure parameter.
91 IP4_CONFIG_VARIABLE
*Variable
;
92 IP4_CONFIG_VARIABLE
*NewVariable
;
93 NIC_IP4_CONFIG_INFO
*Config
;
96 // Read the configuration parameter for this NicAddr from
99 Variable
= Ip4ConfigReadVariable ();
101 if (Variable
== NULL
) {
105 Config
= Ip4ConfigFindNicVariable (Variable
, NicAddr
);
107 if (Config
== NULL
) {
108 NetFreePool (Variable
);
113 // Validate the configuration, if the configuration is invalid,
114 // remove it from the variable.
116 if (!Ip4ConfigIsValid (Config
)) {
117 NewVariable
= Ip4ConfigModifyVariable (Variable
, &Config
->NicAddr
, NULL
);
118 Ip4ConfigWriteVariable (NewVariable
);
120 if (NewVariable
!= NULL
) {
121 NetFreePool (NewVariable
);
124 NetFreePool (Config
);
128 NetFreePool (Variable
);
134 Get the configure parameter for this NIC.
136 @param This The NIC IP4 CONFIG protocol
137 @param ConfigLen The length of the NicConfig buffer.
138 @param NicConfig The buffer to receive the NIC's configure
141 @retval EFI_INVALID_PARAMETER This or ConfigLen is NULL
142 @retval EFI_NOT_FOUND There is no configure parameter for the NIC in
148 EfiNicIp4ConfigGetInfo (
149 IN EFI_NIC_IP4_CONFIG_PROTOCOL
*This
,
150 IN OUT UINTN
*ConfigLen
,
151 OUT NIC_IP4_CONFIG_INFO
*NicConfig
154 IP4_CONFIG_INSTANCE
*Instance
;
155 NIC_IP4_CONFIG_INFO
*Config
;
159 if ((This
== NULL
) || (ConfigLen
== NULL
)) {
160 return EFI_INVALID_PARAMETER
;
164 // Read the Nic's configuration parameter from variable
166 Instance
= IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This
);
167 Config
= Ip4ConfigGetNicInfo (&Instance
->NicAddr
);
169 if (Config
== NULL
) {
170 return EFI_NOT_FOUND
;
174 // Copy the data to user's buffer
176 Len
= SIZEOF_NIC_IP4_CONFIG_INFO (Config
);
178 if ((*ConfigLen
< Len
) || (NicConfig
== NULL
)) {
179 Status
= EFI_BUFFER_TOO_SMALL
;
181 Status
= EFI_SUCCESS
;
182 NetCopyMem (NicConfig
, Config
, Len
);
187 NetFreePool (Config
);
193 Set the IP configure parameters for this NIC. If Reconfig is TRUE,
194 the IP driver will be informed to discard current auto configure
195 parameter and restart the auto configuration process. If current
196 there is a pending auto configuration, EFI_ALREADY_STARTED is
197 returned. You can only change the configure setting when either
198 the configure has finished or not started yet. If NicConfig, the
199 NIC's configure parameter is removed from the variable.
201 @param This The NIC IP4 CONFIG protocol
202 @param NicConfig The new NIC IP4 configure parameter
203 @param Reconfig Inform the IP4 driver to restart the auto
206 @retval EFI_INVALID_PARAMETER This is NULL or the configure parameter is
208 @retval EFI_ALREADY_STARTED There is a pending auto configuration.
209 @retval EFI_NOT_FOUND No auto configure parameter is found
214 EfiNicIp4ConfigSetInfo (
215 IN EFI_NIC_IP4_CONFIG_PROTOCOL
*This
,
216 IN NIC_IP4_CONFIG_INFO
*NicConfig
, OPTIONAL
220 IP4_CONFIG_INSTANCE
*Instance
;
221 IP4_CONFIG_VARIABLE
*Variable
;
222 IP4_CONFIG_VARIABLE
*NewVariable
;
226 // Validate the parameters
229 return EFI_INVALID_PARAMETER
;
232 Instance
= IP4_CONFIG_INSTANCE_FROM_NIC_IP4CONFIG (This
);
234 if ((NicConfig
!= NULL
) && (!Ip4ConfigIsValid (NicConfig
) ||
235 !NIC_ADDR_EQUAL (&NicConfig
->NicAddr
, &Instance
->NicAddr
))) {
236 return EFI_INVALID_PARAMETER
;
239 if (Instance
->State
== IP4_CONFIG_STATE_STARTED
) {
240 return EFI_ALREADY_STARTED
;
244 // Update the parameter in the configure variable
246 Variable
= Ip4ConfigReadVariable ();
248 if ((Variable
== NULL
) && (NicConfig
== NULL
)) {
249 return EFI_NOT_FOUND
;
252 NewVariable
= Ip4ConfigModifyVariable (Variable
, &Instance
->NicAddr
, NicConfig
);
253 Status
= Ip4ConfigWriteVariable (NewVariable
);
255 if (NewVariable
!= NULL
) {
256 NetFreePool (NewVariable
);
260 // Variable is NULL when saving the first configure parameter
262 if (Variable
!= NULL
) {
263 NetFreePool (Variable
);
266 if (EFI_ERROR (Status
)) {
271 // Signal the IP4 to run the auto configuration again
273 if (Reconfig
&& (Instance
->ReconfigEvent
!= NULL
)) {
274 Status
= gBS
->SignalEvent (Instance
->ReconfigEvent
);
282 Start the auto configuration process.
284 @param This The IP4 configure protocol
285 @param DoneEvent The event to signal when auto configure is done
286 @param ReconfigEvent The event to signal when reconfigure is necessary.
288 @retval EFI_INVALID_PARAMETER One of the function parameters is NULL.
289 @retval EFI_ALREADY_STARTED The auto configuration has already started.
290 @retval EFI_SUCCESS The auto configure is successfully started.
296 IN EFI_IP4_CONFIG_PROTOCOL
*This
,
297 IN EFI_EVENT DoneEvent
,
298 IN EFI_EVENT ReconfigEvent
301 IP4_CONFIG_INSTANCE
*Instance
;
302 EFI_DHCP4_PROTOCOL
*Dhcp4
;
303 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
304 EFI_DHCP4_PACKET_OPTION
*OptionList
[1];
305 IP4_CONFIG_DHCP4_OPTION ParaList
;
310 if ((This
== NULL
) || (DoneEvent
== NULL
) || (ReconfigEvent
== NULL
)) {
311 return EFI_INVALID_PARAMETER
;
314 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
316 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
318 if (Instance
->State
!= IP4_CONFIG_STATE_IDLE
) {
319 Status
= EFI_ALREADY_STARTED
;
324 Instance
->DoneEvent
= DoneEvent
;
325 Instance
->ReconfigEvent
= ReconfigEvent
;
327 Instance
->NicConfig
= Ip4ConfigGetNicInfo (&Instance
->NicAddr
);
329 if (Instance
->NicConfig
== NULL
) {
330 Source
= IP4_CONFIG_SOURCE_DHCP
;
332 Source
= Instance
->NicConfig
->Source
;
336 // If the source is static, the auto configuration is done.
339 if (Source
== IP4_CONFIG_SOURCE_STATIC
) {
340 Instance
->State
= IP4_CONFIG_STATE_CONFIGURED
;
341 Instance
->Result
= EFI_SUCCESS
;
343 gBS
->SignalEvent (Instance
->DoneEvent
);
344 Status
= EFI_SUCCESS
;
349 // Start the dhcp process
351 ASSERT ((Source
== IP4_CONFIG_SOURCE_DHCP
) && (Instance
->Dhcp4
== NULL
));
353 Status
= NetLibCreateServiceChild (
354 Instance
->Controller
,
356 &gEfiDhcp4ServiceBindingProtocolGuid
,
357 &Instance
->Dhcp4Handle
360 if (EFI_ERROR (Status
)) {
364 Status
= gBS
->OpenProtocol (
365 Instance
->Dhcp4Handle
,
366 &gEfiDhcp4ProtocolGuid
,
367 (VOID
**) &Instance
->Dhcp4
,
369 Instance
->Controller
,
370 EFI_OPEN_PROTOCOL_BY_DRIVER
373 if (EFI_ERROR (Status
)) {
378 // Check the current DHCP status, if the DHCP process has
379 // already finished, return now.
381 Dhcp4
= Instance
->Dhcp4
;
382 Status
= Dhcp4
->GetModeData (Dhcp4
, &Dhcp4Mode
);
384 if (EFI_ERROR (Status
)) {
388 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
389 Ip4ConfigOnDhcp4Complete (NULL
, Instance
);
395 // Try to start the DHCP process. Use most of the current
396 // DHCP configuration to avoid problems if some DHCP client
397 // yields the control of this DHCP service to us.
399 ParaList
.Head
.OpCode
= DHCP_TAG_PARA_LIST
;
400 ParaList
.Head
.Length
= 2;
401 ParaList
.Head
.Data
[0] = DHCP_TAG_NETMASK
;
402 ParaList
.Route
= DHCP_TAG_ROUTER
;
403 OptionList
[0] = &ParaList
.Head
;
404 Dhcp4Mode
.ConfigData
.OptionCount
= 1;
405 Dhcp4Mode
.ConfigData
.OptionList
= OptionList
;
407 Status
= Dhcp4
->Configure (Dhcp4
, &Dhcp4Mode
.ConfigData
);
409 if (EFI_ERROR (Status
)) {
414 // Start the DHCP process
416 Status
= gBS
->CreateEvent (
419 Ip4ConfigOnDhcp4Complete
,
421 &Instance
->Dhcp4Event
424 if (EFI_ERROR (Status
)) {
428 Status
= Dhcp4
->Start (Dhcp4
, Instance
->Dhcp4Event
);
430 if (EFI_ERROR (Status
)) {
434 Instance
->State
= IP4_CONFIG_STATE_STARTED
;
435 Instance
->Result
= EFI_NOT_READY
;
438 if (EFI_ERROR (Status
)) {
439 Ip4ConfigCleanConfig (Instance
);
443 NET_RESTORE_TPL (OldTpl
);
450 Stop the current auto configuration
452 @param This The IP4 CONFIG protocol
454 @retval EFI_INVALID_PARAMETER This is NULL.
455 @retval EFI_NOT_STARTED The auto configuration hasn't been started.
456 @retval EFI_SUCCESS The auto configuration has been stopped.
462 IN EFI_IP4_CONFIG_PROTOCOL
*This
465 IP4_CONFIG_INSTANCE
*Instance
;
470 return EFI_INVALID_PARAMETER
;
473 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
475 Status
= EFI_SUCCESS
;
476 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
478 if (Instance
->State
== IP4_CONFIG_STATE_IDLE
) {
479 Status
= EFI_NOT_STARTED
;
484 // Release all the configure parameters. Don't signal the user
485 // event. The user wants to abort the configuration, this isn't
486 // the configuration done or reconfiguration.
488 Ip4ConfigCleanConfig (Instance
);
491 NET_RESTORE_TPL (OldTpl
);
498 Get the current outcome of the auto configuration process
500 @param This The IP4 CONFIG protocol
501 @param ConfigDataSize The size of the configure data
502 @param ConfigData The buffer to save the configure data
504 @retval EFI_INVALID_PARAMETER This or ConfigDataSize is NULL
505 @retval EFI_BUFFER_TOO_SMALL The buffer is too small. The needed size is
506 returned in the ConfigDataSize.
507 @retval EFI_SUCCESS The configure data is put in the buffer
512 EfiIp4ConfigGetData (
513 IN EFI_IP4_CONFIG_PROTOCOL
*This
,
514 IN OUT UINTN
*ConfigDataSize
,
515 OUT EFI_IP4_IPCONFIG_DATA
*ConfigData OPTIONAL
518 IP4_CONFIG_INSTANCE
*Instance
;
519 NIC_IP4_CONFIG_INFO
*NicConfig
;
524 if ((This
== NULL
) || (ConfigDataSize
== NULL
)) {
525 return EFI_INVALID_PARAMETER
;
528 Instance
= IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This
);
530 Status
= EFI_SUCCESS
;
531 OldTpl
= NET_RAISE_TPL (NET_TPL_LOCK
);
533 if (Instance
->State
== IP4_CONFIG_STATE_IDLE
) {
534 Status
= EFI_NOT_STARTED
;
535 } else if (Instance
->State
== IP4_CONFIG_STATE_STARTED
) {
536 Status
= EFI_NOT_READY
;
539 if (EFI_ERROR (Status
)) {
544 // Copy the configure data if auto configuration succeeds.
546 Status
= Instance
->Result
;
548 if (Status
== EFI_SUCCESS
) {
549 ASSERT (Instance
->NicConfig
!= NULL
);
551 NicConfig
= Instance
->NicConfig
;
552 Len
= SIZEOF_IP4_CONFIG_INFO (&NicConfig
->Ip4Info
);
554 if ((*ConfigDataSize
< Len
) || (ConfigData
== NULL
)) {
555 Status
= EFI_BUFFER_TOO_SMALL
;
557 NetCopyMem (ConfigData
, &NicConfig
->Ip4Info
, Len
);
560 *ConfigDataSize
= Len
;
564 NET_RESTORE_TPL (OldTpl
);
571 Callback function when DHCP process finished. It will save the
572 retrieved IP configure parameter from DHCP to the NVRam.
574 @param Event The callback event
575 @param Context Opaque context to the callback
582 Ip4ConfigOnDhcp4Complete (
587 IP4_CONFIG_INSTANCE
*Instance
;
588 EFI_DHCP4_MODE_DATA Dhcp4Mode
;
589 EFI_IP4_IPCONFIG_DATA
*Ip4Config
;
594 Instance
= (IP4_CONFIG_INSTANCE
*) Context
;
595 ASSERT (Instance
->Dhcp4
!= NULL
);
597 Instance
->State
= IP4_CONFIG_STATE_CONFIGURED
;
598 Instance
->Result
= EFI_TIMEOUT
;
601 // Get the DHCP retrieved parameters
603 Status
= Instance
->Dhcp4
->GetModeData (Instance
->Dhcp4
, &Dhcp4Mode
);
605 if (EFI_ERROR (Status
)) {
609 if (Dhcp4Mode
.State
== Dhcp4Bound
) {
611 // Save the new configuration retrieved by DHCP both in
612 // the instance and to NVRam. So, both the IP4 driver and
613 // other user can get that address.
617 if (Instance
->NicConfig
!= NULL
) {
618 ASSERT (Instance
->NicConfig
->Source
== IP4_CONFIG_SOURCE_DHCP
);
619 Perment
= Instance
->NicConfig
->Perment
;
620 NetFreePool (Instance
->NicConfig
);
623 Instance
->NicConfig
= NetAllocatePool (sizeof (NIC_IP4_CONFIG_INFO
) +
624 sizeof (EFI_IP4_ROUTE_TABLE
));
626 if (Instance
->NicConfig
== NULL
) {
627 Instance
->Result
= EFI_OUT_OF_RESOURCES
;
631 CopyMem (&Instance
->NicConfig
->NicAddr
, &Instance
->NicAddr
, sizeof (NIC_ADDR
));
632 Instance
->NicConfig
->Source
= IP4_CONFIG_SOURCE_DHCP
;
633 Instance
->NicConfig
->Perment
= Perment
;
635 Ip4Config
= &Instance
->NicConfig
->Ip4Info
;
636 Ip4Config
->StationAddress
= Dhcp4Mode
.ClientAddress
;
637 Ip4Config
->SubnetMask
= Dhcp4Mode
.SubnetMask
;
640 // Create a route for the connected network
642 Ip4Config
->RouteTableSize
= 1;
644 Subnet
= EFI_NTOHL (Dhcp4Mode
.ClientAddress
) & EFI_NTOHL (Dhcp4Mode
.SubnetMask
);
646 EFI_IP4 (Ip4Config
->RouteTable
[0].SubnetAddress
) = HTONL (Subnet
);
647 Ip4Config
->RouteTable
[0].SubnetMask
= Dhcp4Mode
.SubnetMask
;
648 EFI_IP4 (Ip4Config
->RouteTable
[0].GatewayAddress
) = 0;
651 // Create a route if there is a default router.
653 if (EFI_IP4 (Dhcp4Mode
.RouterAddress
) != 0) {
654 Ip4Config
->RouteTableSize
= 2;
655 EFI_IP4 (Ip4Config
->RouteTable
[1].SubnetAddress
) = 0;
656 EFI_IP4 (Ip4Config
->RouteTable
[1].SubnetMask
) = 0;
657 Ip4Config
->RouteTable
[1].GatewayAddress
= Dhcp4Mode
.RouterAddress
;
660 Instance
->Result
= EFI_SUCCESS
;
663 // ignore the return status of EfiNicIp4ConfigSetInfo. Network
664 // stack can operate even that failed.
666 EfiNicIp4ConfigSetInfo (&Instance
->NicIp4Protocol
, Instance
->NicConfig
, FALSE
);
670 gBS
->SignalEvent (Instance
->DoneEvent
);
671 Ip4ConfigCleanDhcp4 (Instance
);
677 Release all the DHCP related resources.
679 @param This The IP4 configure instance
685 Ip4ConfigCleanDhcp4 (
686 IN IP4_CONFIG_INSTANCE
*This
689 if (This
->Dhcp4
!= NULL
) {
690 This
->Dhcp4
->Stop (This
->Dhcp4
);
694 &gEfiDhcp4ProtocolGuid
,
702 if (This
->Dhcp4Handle
!= NULL
) {
703 NetLibDestroyServiceChild (
706 &gEfiDhcp4ServiceBindingProtocolGuid
,
710 This
->Dhcp4Handle
= NULL
;
713 if (This
->Dhcp4Event
== NULL
) {
714 gBS
->CloseEvent (This
->Dhcp4Event
);
715 This
->Dhcp4Event
= NULL
;
721 Clean up all the configuration parameters
723 @param Instance The IP4 configure instance
729 Ip4ConfigCleanConfig (
730 IN IP4_CONFIG_INSTANCE
*Instance
733 if (Instance
->NicConfig
!= NULL
) {
734 NetFreePool (Instance
->NicConfig
);
735 Instance
->NicConfig
= NULL
;
738 Instance
->State
= IP4_CONFIG_STATE_IDLE
;
739 Instance
->DoneEvent
= NULL
;
740 Instance
->ReconfigEvent
= NULL
;
742 Ip4ConfigCleanDhcp4 (Instance
);
745 EFI_IP4_CONFIG_PROTOCOL mIp4ConfigProtocolTemplate
= {
751 EFI_NIC_IP4_CONFIG_PROTOCOL mNicIp4ConfigProtocolTemplate
= {
752 EfiNicIp4ConfigGetName
,
753 EfiNicIp4ConfigGetInfo
,
754 EfiNicIp4ConfigSetInfo