/** @file\r
The implementation of EFI IPv4 Configuration II Protocol.\r
\r
- Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>\r
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
IpSb->DefaultRouteTable = RouteTable;\r
Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
\r
- if (IpSb->State == IP4_SERVICE_CONFIGED) {\r
+ if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) {\r
IpSb->State = IP4_SERVICE_UNSTARTED;\r
}\r
\r
//\r
Count = 0;\r
\r
- for (Index = IP4_MASK_NUM - 1; Index >= 0; Index--) {\r
+ for (Index = IP4_MASK_MAX; Index >= 0; Index--) {\r
\r
NET_LIST_FOR_EACH (Entry, &(IpSb->DefaultRouteTable->RouteArea[Index])) {\r
RtEntry = NET_LIST_USER_STRUCT (Entry, IP4_ROUTE_ENTRY, Link);\r
/**\r
Set the station address and subnetmask for the default interface.\r
\r
- @param[in] Instance The pointer to the IP4 config2 instance data.\r
+ @param[in] IpSb The pointer to the IP4 service binding instance.\r
@param[in] StationAddress Ip address to be set.\r
@param[in] SubnetMask Subnet to be set.\r
\r
**/\r
EFI_STATUS\r
Ip4Config2SetDefaultAddr (\r
- IN IP4_CONFIG2_INSTANCE *Instance,\r
+ IN IP4_SERVICE *IpSb,\r
IN IP4_ADDR StationAddress,\r
IN IP4_ADDR SubnetMask\r
)\r
{\r
EFI_STATUS Status;\r
- IP4_SERVICE *IpSb;\r
IP4_INTERFACE *IpIf;\r
IP4_PROTOCOL *Ip4Instance;\r
EFI_ARP_PROTOCOL *Arp;\r
IP4_ADDR Subnet;\r
IP4_ROUTE_TABLE *RouteTable;\r
\r
- IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
IpIf = IpSb->DefaultInterface;\r
ASSERT (IpIf != NULL);\r
\r
return EFI_SUCCESS;\r
}\r
\r
- //\r
- // The default address is changed, free the previous interface first.\r
- //\r
- if (IpSb->DefaultRouteTable != NULL) {\r
- Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
- IpSb->DefaultRouteTable = NULL; \r
- }\r
+ if (IpSb->Reconfig) {\r
+ //\r
+ // The default address is changed, free the previous interface first.\r
+ //\r
+ if (IpSb->DefaultRouteTable != NULL) {\r
+ Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
+ IpSb->DefaultRouteTable = NULL; \r
+ }\r
\r
- Ip4CancelReceive (IpSb->DefaultInterface);\r
- Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
- IpSb->DefaultInterface = NULL;\r
- //\r
- // Create new default interface and route table.\r
- // \r
- IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
- if (IpIf == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ Ip4CancelReceive (IpSb->DefaultInterface);\r
+ Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
+ IpSb->DefaultInterface = NULL;\r
+ //\r
+ // Create new default interface and route table.\r
+ // \r
+ IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
+ if (IpIf == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
\r
- RouteTable = Ip4CreateRouteTable ();\r
- if (RouteTable == NULL) {\r
- Ip4FreeInterface (IpIf, NULL);\r
- return EFI_OUT_OF_RESOURCES;\r
+ RouteTable = Ip4CreateRouteTable ();\r
+ if (RouteTable == NULL) {\r
+ Ip4FreeInterface (IpIf, NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ IpSb->DefaultInterface = IpIf;\r
+ InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
+ IpSb->DefaultRouteTable = RouteTable;\r
+ Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
}\r
- \r
- IpSb->DefaultInterface = IpIf;\r
- InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
- IpSb->DefaultRouteTable = RouteTable;\r
- Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
\r
if (IpSb->State == IP4_SERVICE_CONFIGED) {\r
IpSb->State = IP4_SERVICE_UNSTARTED;\r
);\r
\r
IpSb->State = IP4_SERVICE_CONFIGED;\r
+ IpSb->Reconfig = FALSE;\r
+ \r
return EFI_SUCCESS;\r
}\r
\r
EFI_STATUS Status;\r
IP4_SERVICE *IpSb;\r
\r
- Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);\r
+ IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
+\r
+ //\r
+ // Check whether the StationAddress/SubnetMask pair is valid.\r
+ //\r
+ if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
//\r
// Create a route if there is a default router.\r
//\r
- IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
if (GatewayAddress != IP4_ALLZERO_ADDRESS) {\r
Ip4AddRoute (\r
IpSb->DefaultRouteTable,\r
}\r
}\r
\r
+/**\r
+ This worker function sets the DNS server list for the EFI IPv4 network\r
+ stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL\r
+ manages. The DNS server addresses must be unicast IPv4 addresses. \r
+\r
+ @param[in] Instance The pointer to the IP4 config2 instance data.\r
+ @param[in] DataSize The size of the buffer pointed to by Data in bytes.\r
+ @param[in] Data The data buffer to set, points to an array of\r
+ EFI_IPv4_ADDRESS instances.\r
+\r
+ @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.\r
+ @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.\r
+ @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.\r
+ @retval EFI_ABORTED The DNS server addresses to be set equal the current\r
+ configuration.\r
+ @retval EFI_SUCCESS The specified configuration data for the EFI IPv4\r
+ network stack was set.\r
+\r
+**/\r
+EFI_STATUS\r
+Ip4Config2SetDnsServerWorker (\r
+ IN IP4_CONFIG2_INSTANCE *Instance,\r
+ IN UINTN DataSize,\r
+ IN VOID *Data\r
+ )\r
+{\r
+ UINTN OldIndex;\r
+ UINTN NewIndex;\r
+ EFI_IPv4_ADDRESS *OldDns;\r
+ EFI_IPv4_ADDRESS *NewDns;\r
+ UINTN OldDnsCount;\r
+ UINTN NewDnsCount;\r
+ IP4_CONFIG2_DATA_ITEM *Item;\r
+ BOOLEAN OneAdded;\r
+ VOID *Tmp;\r
+ IP4_ADDR DnsAddress;\r
+\r
+ if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {\r
+ return EFI_BAD_BUFFER_SIZE;\r
+ }\r
+\r
+ Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
+ NewDns = (EFI_IPv4_ADDRESS *) Data;\r
+ OldDns = Item->Data.DnsServers;\r
+ NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS); \r
+ OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
+ OneAdded = FALSE;\r
+\r
+ if (NewDnsCount != OldDnsCount) {\r
+ Tmp = AllocatePool (DataSize);\r
+ if (Tmp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ } else {\r
+ Tmp = NULL;\r
+ }\r
+\r
+ for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
+ CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));\r
+ if (IP4_IS_UNSPECIFIED (NTOHL (DnsAddress)) || IP4_IS_LOCAL_BROADCAST (NTOHL (DnsAddress))) {\r
+ //\r
+ // The dns server address must be unicast.\r
+ //\r
+ if (Tmp != NULL) {\r
+ FreePool (Tmp);\r
+ }\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (OneAdded) {\r
+ //\r
+ // If any address in the new setting is not in the old settings, skip the\r
+ // comparision below.\r
+ //\r
+ continue;\r
+ }\r
+\r
+ for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {\r
+ if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {\r
+ //\r
+ // If found break out.\r
+ //\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (OldIndex == OldDnsCount) {\r
+ OneAdded = TRUE;\r
+ }\r
+ }\r
+\r
+ if (!OneAdded && (DataSize == Item->DataSize)) {\r
+ //\r
+ // No new item is added and the size is the same.\r
+ //\r
+ Item->Status = EFI_SUCCESS;\r
+ return EFI_ABORTED;\r
+ } else {\r
+ if (Tmp != NULL) {\r
+ if (Item->Data.Ptr != NULL) {\r
+ FreePool (Item->Data.Ptr);\r
+ } \r
+ Item->Data.Ptr = Tmp;\r
+ }\r
+\r
+ CopyMem (Item->Data.Ptr, Data, DataSize);\r
+ Item->DataSize = DataSize;\r
+ Item->Status = EFI_SUCCESS;\r
+ return EFI_SUCCESS;\r
+ }\r
+}\r
+\r
+\r
\r
/**\r
Callback function when DHCP process finished. It will save the\r
IP4_ADDR StationAddress;\r
IP4_ADDR SubnetMask;\r
IP4_ADDR GatewayAddress;\r
+ UINT32 Index;\r
+ UINT32 OptionCount;\r
+ EFI_DHCP4_PACKET_OPTION **OptionList;\r
\r
Instance = (IP4_CONFIG2_INSTANCE *) Context;\r
ASSERT (Instance->Dhcp4 != NULL);\r
goto Exit;\r
}\r
\r
+ //\r
+ // Parse the ACK to get required DNS server information.\r
+ //\r
+ OptionCount = 0;\r
+ OptionList = NULL;\r
+\r
+ Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ goto Exit;\r
+ }\r
+\r
+ OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
+ if (OptionList == NULL) {\r
+ goto Exit;\r
+ }\r
+\r
+ Status = Instance->Dhcp4->Parse (Instance->Dhcp4, Dhcp4Mode.ReplyPacket, &OptionCount, OptionList);\r
+ if (EFI_ERROR (Status)) {\r
+ FreePool (OptionList);\r
+ goto Exit;\r
+ }\r
+\r
+ for (Index = 0; Index < OptionCount; Index++) {\r
+ //\r
+ // Look for DNS Server opcode (6).\r
+ //\r
+ if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) {\r
+ if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) {\r
+ break;\r
+ }\r
+\r
+ Ip4Config2SetDnsServerWorker (Instance, OptionList[Index]->Length, &OptionList[Index]->Data[0]);\r
+ break;\r
+ }\r
+ }\r
+\r
+ FreePool (OptionList);\r
+\r
Instance->DhcpSuccess = TRUE;\r
}\r
\r
\r
@param[in] Instance The IP4 config2 instance to configure\r
\r
- @retval EFI_SUCCESS The auto configuration is successfull started\r
+ @retval EFI_SUCCESS The auto configuration is successfully started\r
@retval Others Failed to start auto configuration.\r
\r
**/\r
// DHCP configuration to avoid problems if some DHCP client\r
// yields the control of this DHCP service to us.\r
//\r
- ParaList.Head.OpCode = DHCP_TAG_PARA_LIST;\r
- ParaList.Head.Length = 2;\r
- ParaList.Head.Data[0] = DHCP_TAG_NETMASK;\r
- ParaList.Route = DHCP_TAG_ROUTER;\r
+ ParaList.Head.OpCode = DHCP4_TAG_PARA_LIST;\r
+ ParaList.Head.Length = 3;\r
+ ParaList.Head.Data[0] = DHCP4_TAG_NETMASK;\r
+ ParaList.Route = DHCP4_TAG_ROUTER;\r
+ ParaList.Dns = DHCP4_TAG_DNS_SERVER;\r
OptionList[0] = &ParaList.Head;\r
Dhcp4Mode.ConfigData.OptionCount = 1;\r
Dhcp4Mode.ConfigData.OptionList = OptionList;\r
IN VOID *Data OPTIONAL\r
)\r
{\r
-\r
IP4_SERVICE *IpSb;\r
UINTN Length;\r
IP4_CONFIG2_DATA_ITEM *Item;\r
}\r
\r
if (NewPolicy == Instance->Policy) {\r
- return EFI_ABORTED;\r
+ if (NewPolicy != Ip4Config2PolicyDhcp || Instance->DhcpSuccess) {\r
+ return EFI_ABORTED;\r
+ }\r
} else {\r
- if (NewPolicy == Ip4Config2PolicyDhcp) {\r
- //\r
- // The policy is changed from static to dhcp:\r
- // Clean the ManualAddress, Gateway and DnsServers, shrink the variable\r
- // data size, and fire up all the related events.\r
- //\r
- DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
- }\r
- DataItem->Data.Ptr = NULL;\r
- DataItem->DataSize = 0;\r
- DataItem->Status = EFI_NOT_FOUND;\r
- NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+ //\r
+ // The policy is changed. Clean the ManualAddress, Gateway and DnsServers, \r
+ // shrink the variable data size, and fire up all the related events.\r
+ //\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
+ NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
\r
- DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
- }\r
- DataItem->Data.Ptr = NULL;\r
- DataItem->DataSize = 0;\r
- DataItem->Status = EFI_NOT_FOUND;\r
- NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
+ NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
\r
- DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
- }\r
- DataItem->Data.Ptr = NULL;\r
- DataItem->DataSize = 0;\r
- DataItem->Status = EFI_NOT_FOUND;\r
- NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
+ NetMapIterate (&DataItem->EventMap, Ip4Config2SignalEvent, NULL);\r
+ \r
+ if (NewPolicy == Ip4Config2PolicyDhcp) {\r
+ SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_VOLATILE);\r
} else {\r
//\r
// The policy is changed from dhcp to static. Stop the DHCPv4 process\r
//\r
if (Instance->Dhcp4Event != NULL) {\r
gBS->CloseEvent (Instance->Dhcp4Event);\r
+ Instance->Dhcp4Event = NULL;\r
}\r
}\r
}\r
\r
**/\r
EFI_STATUS\r
-Ip4Config2SetMaunualAddress (\r
+Ip4Config2SetManualAddress (\r
IN IP4_CONFIG2_INSTANCE *Instance,\r
IN UINTN DataSize,\r
IN VOID *Data\r
IP4_ADDR StationAddress;\r
IP4_ADDR SubnetMask;\r
VOID *Ptr;\r
+ IP4_SERVICE *IpSb;\r
+ IP4_INTERFACE *IpIf;\r
+ IP4_ROUTE_TABLE *RouteTable;\r
+\r
+ DataItem = NULL;\r
+ Status = EFI_SUCCESS;\r
+ Ptr = NULL;\r
+ IpIf = NULL;\r
+ RouteTable = NULL;\r
+\r
+ IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
\r
ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);\r
\r
- if (((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0) || (DataSize == 0)) {\r
+ if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0)) {\r
return EFI_BAD_BUFFER_SIZE;\r
}\r
\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
- NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
\r
- //\r
- // Store the new data, and init the DataItem status to EFI_NOT_READY because\r
- // we may have an asynchronous configuration process.\r
- //\r
- Ptr = AllocateCopyPool (DataSize, Data);\r
- if (Ptr == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
+ if (Data != NULL && DataSize != 0) {\r
+ NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);\r
\r
- DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
- }\r
- \r
- DataItem->Data.Ptr = Ptr;\r
- DataItem->DataSize = DataSize;\r
- DataItem->Status = EFI_NOT_READY;\r
+ StationAddress = EFI_NTOHL (NewAddress.Address);\r
+ SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
\r
- StationAddress = EFI_NTOHL (NewAddress.Address);\r
- SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);\r
+ //\r
+ // Check whether the StationAddress/SubnetMask pair is valid.\r
+ //\r
+ if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- Status = Ip4Config2SetDefaultAddr (Instance, StationAddress, SubnetMask);\r
- if (EFI_ERROR (Status)) {\r
- goto ON_EXIT;\r
- } \r
+ //\r
+ // Store the new data, and init the DataItem status to EFI_NOT_READY because\r
+ // we may have an asynchronous configuration process.\r
+ //\r
+ Ptr = AllocateCopyPool (DataSize, Data);\r
+ if (Ptr == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ \r
+ DataItem->Data.Ptr = Ptr;\r
+ DataItem->DataSize = DataSize;\r
+ DataItem->Status = EFI_NOT_READY;\r
+\r
+ IpSb->Reconfig = TRUE;\r
+ Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);\r
+\r
+ DataItem->Status = Status;\r
+\r
+ if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) {\r
+ if (Ptr != NULL) {\r
+ FreePool (Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL; \r
+ }\r
+ } else {\r
+ //\r
+ // DataSize is 0 and Data is NULL, clean up the manual address.\r
+ //\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
+\r
+ //\r
+ // Free the default router table and Interface, clean up the assemble table.\r
+ //\r
+ if (IpSb->DefaultInterface != NULL) {\r
+ if (IpSb->DefaultRouteTable != NULL) {\r
+ Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
+ IpSb->DefaultRouteTable = NULL; \r
+ }\r
+\r
+ Ip4CancelReceive (IpSb->DefaultInterface);\r
+\r
+ Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
+ IpSb->DefaultInterface = NULL;\r
+ }\r
+\r
+ Ip4CleanAssembleTable (&IpSb->Assemble);\r
\r
- DataItem->Status = EFI_SUCCESS; \r
+ //\r
+ // Create new default interface and route table.\r
+ // \r
+ IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
+ if (IpIf == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ RouteTable = Ip4CreateRouteTable ();\r
+ if (RouteTable == NULL) {\r
+ Ip4FreeInterface (IpIf, NULL);\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ \r
+ IpSb->DefaultInterface = IpIf;\r
+ InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
+ IpSb->DefaultRouteTable = RouteTable;\r
+ Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
\r
-ON_EXIT:\r
- if (EFI_ERROR (DataItem->Status)) {\r
- if (Ptr != NULL) {\r
- FreePool (Ptr);\r
+ //\r
+ // Reset the State to unstarted. \r
+ //\r
+ if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) {\r
+ IpSb->State = IP4_SERVICE_UNSTARTED;\r
}\r
- DataItem->Data.Ptr = NULL; \r
}\r
\r
- return EFI_SUCCESS;\r
+ return Status;\r
}\r
\r
/**\r
BOOLEAN OneAdded;\r
VOID *Tmp;\r
\r
- if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {\r
+ OldGateway = NULL;\r
+ NewGateway = NULL;\r
+ OneRemoved = FALSE;\r
+ OneAdded = FALSE;\r
+ Tmp = NULL;\r
+\r
+ if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv4_ADDRESS) != 0)) {\r
return EFI_BAD_BUFFER_SIZE;\r
}\r
\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
-\r
- NewGateway = (EFI_IPv4_ADDRESS *) Data;\r
- NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
- for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
- CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
- \r
- if (!NetIp4IsUnicast (NTOHL (Gateway), 0)) {\r
-\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {\r
- if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
- }\r
- \r
IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);\r
- DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
+\r
+ DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
OldGateway = DataItem->Data.Gateway;\r
OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
- OneRemoved = FALSE;\r
- OneAdded = FALSE;\r
-\r
- if (NewGatewayCount != OldGatewayCount) {\r
- Tmp = AllocatePool (DataSize);\r
- if (Tmp == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- Tmp = NULL;\r
- }\r
\r
for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {\r
//\r
- // Remove this route entry.\r
+ // Remove the old route entry.\r
//\r
CopyMem (&Gateway, OldGateway + Index1, sizeof (IP4_ADDR));\r
Ip4DelRoute (\r
NTOHL (Gateway)\r
);\r
OneRemoved = TRUE;\r
-\r
}\r
\r
- for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
- CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
- Ip4AddRoute (\r
- IpSb->DefaultRouteTable,\r
- IP4_ALLZERO_ADDRESS,\r
- IP4_ALLZERO_ADDRESS,\r
- NTOHL (Gateway)\r
- ); \r
-\r
- OneAdded = TRUE;\r
- }\r
+ if (Data != NULL && DataSize != 0) {\r
+ NewGateway = (EFI_IPv4_ADDRESS *) Data;\r
+ NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
+ for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
+ CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
\r
+ if ((IpSb->DefaultInterface->SubnetMask != 0) && \r
+ !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
\r
- if (!OneRemoved && !OneAdded) {\r
- DataItem->Status = EFI_SUCCESS;\r
- return EFI_ABORTED;\r
- } else {\r
+ for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {\r
+ if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+ }\r
+ }\r
\r
- if (Tmp != NULL) {\r
- if (DataItem->Data.Ptr != NULL) {\r
- FreePool (DataItem->Data.Ptr);\r
+ if (NewGatewayCount != OldGatewayCount) {\r
+ Tmp = AllocatePool (DataSize);\r
+ if (Tmp == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
}\r
- DataItem->Data.Ptr = Tmp;\r
+ } else {\r
+ Tmp = NULL;\r
}\r
\r
- CopyMem (DataItem->Data.Ptr, Data, DataSize);\r
- DataItem->DataSize = DataSize;\r
- DataItem->Status = EFI_SUCCESS;\r
- return EFI_SUCCESS;\r
+ for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {\r
+ //\r
+ // Add the new route entry.\r
+ //\r
+ CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));\r
+ Ip4AddRoute (\r
+ IpSb->DefaultRouteTable,\r
+ IP4_ALLZERO_ADDRESS,\r
+ IP4_ALLZERO_ADDRESS,\r
+ NTOHL (Gateway)\r
+ ); \r
+\r
+ OneAdded = TRUE;\r
+ }\r
+\r
+ if (!OneRemoved && !OneAdded) {\r
+ DataItem->Status = EFI_SUCCESS;\r
+ return EFI_ABORTED;\r
+ } else {\r
+ if (Tmp != NULL) {\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = Tmp;\r
+ }\r
+\r
+ CopyMem (DataItem->Data.Ptr, Data, DataSize);\r
+ DataItem->DataSize = DataSize;\r
+ DataItem->Status = EFI_SUCCESS;\r
+ }\r
+ } else {\r
+ //\r
+ // DataSize is 0 and Data is NULL, clean up the Gateway address.\r
+ //\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ FreePool (DataItem->Data.Ptr);\r
+ }\r
+ DataItem->Data.Ptr = NULL;\r
+ DataItem->DataSize = 0;\r
+ DataItem->Status = EFI_NOT_FOUND;\r
}\r
\r
+ return EFI_SUCCESS;\r
}\r
\r
/**\r
IN VOID *Data\r
)\r
{\r
- UINTN OldIndex;\r
- UINTN NewIndex;\r
- UINTN Index1;\r
- EFI_IPv4_ADDRESS *OldDns;\r
- EFI_IPv4_ADDRESS *NewDns;\r
- UINTN OldDnsCount;\r
- UINTN NewDnsCount;\r
- IP4_CONFIG2_DATA_ITEM *Item;\r
- BOOLEAN OneAdded;\r
- VOID *Tmp;\r
- IP4_ADDR DnsAddress;\r
+ EFI_STATUS Status;\r
+ IP4_CONFIG2_DATA_ITEM *Item;\r
\r
- if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {\r
- return EFI_BAD_BUFFER_SIZE;\r
- }\r
+ Status = EFI_SUCCESS;\r
+ Item = NULL;\r
\r
if (Instance->Policy != Ip4Config2PolicyStatic) {\r
return EFI_WRITE_PROTECTED;\r
}\r
\r
- Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
- NewDns = (EFI_IPv4_ADDRESS *) Data;\r
- OldDns = Item->Data.DnsServers;\r
- NewDnsCount = DataSize / sizeof (EFI_IPv4_ADDRESS);\r
- OldDnsCount = Item->DataSize / sizeof (EFI_IPv4_ADDRESS);\r
- OneAdded = FALSE;\r
+ Item = &Instance->DataItem[Ip4Config2DataTypeDnsServer];\r
\r
- if (NewDnsCount != OldDnsCount) {\r
- Tmp = AllocatePool (DataSize);\r
- if (Tmp == NULL) {\r
- return EFI_OUT_OF_RESOURCES;\r
- }\r
- } else {\r
- Tmp = NULL;\r
+ if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) {\r
+ REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE);\r
}\r
\r
- for (NewIndex = 0; NewIndex < NewDnsCount; NewIndex++) {\r
- CopyMem (&DnsAddress, NewDns + NewIndex, sizeof (IP4_ADDR));\r
-\r
- if (!NetIp4IsUnicast (NTOHL (DnsAddress), 0)) {\r
- //\r
- // The dns server address must be unicast.\r
- //\r
- FreePool (Tmp);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- for (Index1 = NewIndex + 1; Index1 < NewDnsCount; Index1++) {\r
- if (EFI_IP4_EQUAL (NewDns + NewIndex, NewDns + Index1)) {\r
- FreePool (Tmp);\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- }\r
-\r
- if (OneAdded) {\r
- //\r
- // If any address in the new setting is not in the old settings, skip the\r
- // comparision below.\r
- //\r
- continue;\r
- }\r
-\r
- for (OldIndex = 0; OldIndex < OldDnsCount; OldIndex++) {\r
- if (EFI_IP4_EQUAL (NewDns + NewIndex, OldDns + OldIndex)) {\r
- //\r
- // If found break out.\r
- //\r
- break;\r
- }\r
- }\r
-\r
- if (OldIndex == OldDnsCount) {\r
- OneAdded = TRUE;\r
- }\r
- }\r
-\r
- if (!OneAdded && (DataSize == Item->DataSize)) {\r
+ if (Data != NULL && DataSize != 0) {\r
+ Status = Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);\r
+ } else {\r
//\r
- // No new item is added and the size is the same.\r
+ // DataSize is 0 and Data is NULL, clean up the DnsServer address. \r
//\r
- Item->Status = EFI_SUCCESS;\r
- return EFI_ABORTED;\r
- } else {\r
- if (Tmp != NULL) {\r
- if (Item->Data.Ptr != NULL) {\r
- FreePool (Item->Data.Ptr);\r
- } \r
- Item->Data.Ptr = Tmp;\r
+ if (Item->Data.Ptr != NULL) {\r
+ FreePool (Item->Data.Ptr);\r
}\r
-\r
- CopyMem (Item->Data.Ptr, Data, DataSize);\r
- Item->DataSize = DataSize;\r
- Item->Status = EFI_SUCCESS;\r
- return EFI_SUCCESS;\r
+ Item->Data.Ptr = NULL;\r
+ Item->DataSize = 0;\r
+ Item->Status = EFI_NOT_FOUND;\r
}\r
-\r
+ \r
+ return Status;\r
}\r
\r
/**\r
OUT EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo\r
)\r
{\r
- IfInfo->Name[0] = L'e';\r
- IfInfo->Name[1] = L't';\r
- IfInfo->Name[2] = L'h';\r
- IfInfo->Name[3] = (CHAR16) (L'0' + IpSb->Ip4Config2Instance.IfIndex);\r
- IfInfo->Name[4] = 0;\r
+ UnicodeSPrint (\r
+ IfInfo->Name,\r
+ EFI_IP4_CONFIG2_INTERFACE_INFO_NAME_SIZE,\r
+ L"eth%d",\r
+ IpSb->Ip4Config2Instance.IfIndex\r
+ );\r
\r
IfInfo->IfType = IpSb->SnpMode.IfType;\r
IfInfo->HwAddressSize = IpSb->SnpMode.HwAddressSize;\r
network stack was set successfully.\r
@retval EFI_INVALID_PARAMETER One or more of the following are TRUE:\r
- This is NULL.\r
- - Data is NULL.\r
- - One or more fields in Data do not match the requirement of the\r
- data type indicated by DataType.\r
+ - One or more fields in Data and DataSize do not match the \r
+ requirement of the data type indicated by DataType.\r
@retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified\r
configuration data cannot be set under the current policy.\r
@retval EFI_ACCESS_DENIED Another set operation on the specified configuration\r
IP4_CONFIG2_INSTANCE *Instance;\r
IP4_SERVICE *IpSb;\r
\r
- if ((This == NULL) || (Data == NULL)) {\r
+ if ((This == NULL) || (Data == NULL && DataSize != 0) || (Data != NULL && DataSize == 0)) {\r
return EFI_INVALID_PARAMETER;\r
}\r
\r
DataItem->SetData = Ip4Config2SetPolicy;\r
DataItem->Data.Ptr = &Instance->Policy;\r
DataItem->DataSize = sizeof (Instance->Policy);\r
- Instance->Policy = Ip4Config2PolicyDhcp;\r
+ Instance->Policy = Ip4Config2PolicyStatic;\r
SET_DATA_ATTRIB (DataItem->Attribute, DATA_ATTRIB_SIZE_FIXED);\r
\r
DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];\r
- DataItem->SetData = Ip4Config2SetMaunualAddress;\r
+ DataItem->SetData = Ip4Config2SetManualAddress;\r
DataItem->Status = EFI_NOT_FOUND;\r
\r
DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];\r
\r
//\r
// Try to read the config data from NV variable.\r
+ // If not found, write initialized config data into NV variable \r
+ // as a default config data.\r
//\r
Status = Ip4Config2ReadConfigData (IpSb->MacString, Instance);\r
if (Status == EFI_NOT_FOUND) {\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
-\r
- //\r
- // Try to set the configured parameter.\r
- //\r
- for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
- DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
- if (DataItem->Data.Ptr != NULL) {\r
- DataItem->SetData (\r
- &IpSb->Ip4Config2Instance,\r
- DataItem->DataSize,\r
- DataItem->Data.Ptr\r
- );\r
- }\r
- }\r
-\r
+ \r
Instance->Ip4Config2.SetData = EfiIp4Config2SetData;\r
Instance->Ip4Config2.GetData = EfiIp4Config2GetData;\r
Instance->Ip4Config2.RegisterDataNotify = EfiIp4Config2RegisterDataNotify;\r
//\r
if (Instance->Dhcp4Event != NULL) {\r
gBS->CloseEvent (Instance->Dhcp4Event);\r
+ Instance->Dhcp4Event = NULL;\r
}\r
\r
for (Index = 0; Index < Ip4Config2DataTypeMaximum; Index++) {\r
RemoveEntryList (&Instance->Link);\r
}\r
\r
+/**\r
+ The event handle for IP4 auto reconfiguration. The original default\r
+ interface and route table will be removed as the default.\r
+\r
+ @param[in] Context The IP4 service binding instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4AutoReconfigCallBackDpc (\r
+ IN VOID *Context\r
+ )\r
+{\r
+ IP4_SERVICE *IpSb;\r
+\r
+ IpSb = (IP4_SERVICE *) Context;\r
+ NET_CHECK_SIGNATURE (IpSb, IP4_SERVICE_SIGNATURE);\r
+\r
+ if (IpSb->State > IP4_SERVICE_UNSTARTED) {\r
+ IpSb->State = IP4_SERVICE_UNSTARTED;\r
+ }\r
+ \r
+ IpSb->Reconfig = TRUE;\r
+\r
+ Ip4StartAutoConfig (&IpSb->Ip4Config2Instance);\r
+\r
+ return ;\r
+}\r
+\r
+\r
+/**\r
+ Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK.\r
+\r
+ @param Event The event that is signalled.\r
+ @param Context The IP4 service binding instance.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ip4AutoReconfigCallBack (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ //\r
+ // Request Ip4AutoReconfigCallBackDpc as a DPC at TPL_CALLBACK\r
+ //\r
+ QueueDpc (TPL_CALLBACK, Ip4AutoReconfigCallBackDpc, Context);\r
+}\r
+\r