/** @file\r
+ Routines used to operate the Ip4 configure variable.\r
\r
-Copyright (c) 2006 - 2008, Intel Corporation \r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
+which accompanies this distribution. The full text of the license may be found at<BR>\r
http://opensource.org/licenses/bsd-license.php\r
\r
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
\r
-Module Name:\r
-\r
- NicIp4Variable.c\r
-\r
-Abstract:\r
-\r
- Routines used to operate the Ip4 configure variable\r
-\r
-\r
**/\r
\r
-#include <Uefi.h>\r
-\r
-#include <Library/NetLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/MemoryAllocationLib.h>\r
-#include <Library/UefiBootServicesTableLib.h>\r
-#include <Library/UefiRuntimeServicesTableLib.h>\r
-\r
+#include "Ip4Config.h"\r
#include "NicIp4Variable.h"\r
\r
+BOOLEAN mIp4ConfigVariableReclaimed = FALSE;\r
\r
/**\r
Check whether the configure parameter is valid.\r
Netmask = EFI_NTOHL (IpConfig->SubnetMask);\r
\r
if ((Netmask == 0) || !IP4_IS_VALID_NETMASK (Netmask) ||\r
- (Station == 0) || !Ip4IsUnicast (Station, Netmask)) {\r
+ (Station == 0) || !NetIp4IsUnicast (Station, Netmask)) {\r
return FALSE;\r
}\r
\r
Gateway = EFI_NTOHL (IpConfig->RouteTable[Index].GatewayAddress);\r
\r
if ((Gateway != 0) && (!IP4_NET_EQUAL (Station, Gateway, Netmask) ||\r
- !Ip4IsUnicast (Gateway, Netmask))) {\r
+ !NetIp4IsUnicast (Gateway, Netmask))) {\r
return FALSE;\r
}\r
}\r
/**\r
Read the ip4 configure variable from the EFI variable.\r
\r
- None\r
+ @param Instance The IP4 CONFIG instance.\r
\r
- @return The IP4 configure read if it is there and is valid, otherwise NULL\r
+ @return The IP4 configure read if it is there and is valid, otherwise NULL.\r
\r
**/\r
-IP4_CONFIG_VARIABLE *\r
+NIC_IP4_CONFIG_INFO *\r
Ip4ConfigReadVariable (\r
- VOID\r
+ IN IP4_CONFIG_INSTANCE *Instance\r
)\r
{\r
- IP4_CONFIG_VARIABLE *Variable;\r
- EFI_STATUS Status;\r
- UINTN Size;\r
- UINT16 CheckSum;\r
-\r
- //\r
- // Get the size of variable, then allocate a buffer to read the variable.\r
- //\r
- Size = 0;\r
- Variable = NULL;\r
- Status = gRT->GetVariable (\r
- EFI_NIC_IP4_CONFIG_VARIABLE,\r
- &gEfiNicIp4ConfigVariableGuid,\r
- NULL,\r
- &Size,\r
- NULL\r
- );\r
-\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- return NULL;\r
- }\r
-\r
- if (Size < sizeof (IP4_CONFIG_VARIABLE)) {\r
- goto REMOVE_VARIABLE;\r
- }\r
-\r
- Variable = AllocatePool (Size);\r
-\r
- if (Variable == NULL) {\r
- return NULL;\r
- }\r
-\r
- Status = gRT->GetVariable (\r
- EFI_NIC_IP4_CONFIG_VARIABLE,\r
- &gEfiNicIp4ConfigVariableGuid,\r
- NULL,\r
- &Size,\r
- Variable\r
- );\r
-\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
-\r
- //\r
- // Verify the checksum, variable size and count\r
- //\r
- CheckSum = (UINT16) (~NetblockChecksum ((UINT8 *) Variable, (UINT32)Size));\r
-\r
- if ((CheckSum != 0) || (Size != Variable->Len)) {\r
- goto REMOVE_VARIABLE;\r
- }\r
-\r
- if ((Variable->Count < 1) || (Variable->Count > MAX_IP4_CONFIG_IN_VARIABLE)) {\r
- goto REMOVE_VARIABLE;\r
- }\r
+ NIC_IP4_CONFIG_INFO *NicConfig;\r
\r
- return Variable;\r
-\r
-REMOVE_VARIABLE:\r
- Ip4ConfigWriteVariable (NULL);\r
-\r
-ON_ERROR:\r
- if (Variable != NULL) {\r
- gBS->FreePool (Variable);\r
+ GetVariable2 (Instance->MacString, &gEfiNicIp4ConfigVariableGuid, (VOID**)&NicConfig, NULL);\r
+ if (NicConfig != NULL) {\r
+ Ip4ConfigFixRouteTablePointer (&NicConfig->Ip4Info);\r
}\r
\r
- return NULL;\r
+ return NicConfig;\r
}\r
\r
-\r
/**\r
Write the IP4 configure variable to the NVRAM. If Config\r
is NULL, remove the variable.\r
\r
- @param Config The IP4 configure data to write\r
+ @param Instance The IP4 CONFIG instance.\r
+ @param NicConfig The IP4 configure data to write.\r
\r
- @retval EFI_SUCCESS The variable is written to the NVRam\r
+ @retval EFI_SUCCESS The variable is written to the NVRam.\r
@retval Others Failed to write the variable.\r
\r
**/\r
EFI_STATUS\r
Ip4ConfigWriteVariable (\r
- IN IP4_CONFIG_VARIABLE *Config OPTIONAL\r
+ IN IP4_CONFIG_INSTANCE *Instance,\r
+ IN NIC_IP4_CONFIG_INFO *NicConfig OPTIONAL\r
)\r
{\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
\r
Status = gRT->SetVariable (\r
- EFI_NIC_IP4_CONFIG_VARIABLE,\r
+ Instance->MacString,\r
&gEfiNicIp4ConfigVariableGuid,\r
IP4_CONFIG_VARIABLE_ATTRIBUTES,\r
- (Config == NULL) ? 0 : Config->Len,\r
- Config\r
+ (NicConfig == NULL) ? 0 : SIZEOF_NIC_IP4_CONFIG_INFO (NicConfig),\r
+ NicConfig\r
);\r
\r
return Status;\r
}\r
\r
-\r
/**\r
- Locate the IP4 configure parameters from the variable.If a\r
- configuration is found, copy it to a newly allocated block\r
- of memory to avoid the alignment problem. Caller should\r
- release the memory after use.\r
+ Check whether a NIC exist in the platform given its MAC address.\r
\r
- @param Variable The IP4 configure variable to search in\r
- @param NicAddr The interface address to check\r
+ @param NicAddr The MAC address for the NIC to be checked.\r
\r
- @return The point to the NIC's IP4 configure info if it is found\r
- @return in the IP4 variable, otherwise NULL.\r
+ @retval TRUE The NIC exist in the platform.\r
+ @retval FALSE The NIC doesn't exist in the platform.\r
\r
**/\r
-NIC_IP4_CONFIG_INFO *\r
-Ip4ConfigFindNicVariable (\r
- IN IP4_CONFIG_VARIABLE *Variable,\r
+BOOLEAN\r
+Ip4ConfigIsNicExist (\r
IN NIC_ADDR *NicAddr\r
)\r
{\r
- NIC_IP4_CONFIG_INFO Temp;\r
- NIC_IP4_CONFIG_INFO *Config;\r
- UINT32 Index;\r
- UINT8 *Cur;\r
- UINT32 Len;\r
-\r
- Cur = (UINT8*)&Variable->ConfigInfo;\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN NumberOfHandles;\r
+ UINTN Index;\r
+ BOOLEAN Found;\r
+ UINTN AddrSize;\r
+ EFI_MAC_ADDRESS MacAddr;\r
\r
- for (Index = 0; Index < Variable->Count; Index++) {\r
- //\r
- // Copy the data to Temp to avoid the alignment problems\r
- //\r
- CopyMem (&Temp, Cur, sizeof (NIC_IP4_CONFIG_INFO));\r
- Len = SIZEOF_NIC_IP4_CONFIG_INFO (&Temp);\r
+ //\r
+ // Locate Service Binding handles.\r
+ //\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+ NULL,\r
+ &NumberOfHandles,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return FALSE;\r
+ }\r
\r
+ Found = FALSE;\r
+ for (Index = 0; Index < NumberOfHandles; Index++) {\r
//\r
- // Found the matching configuration parameters, allocate\r
- // a block of memory then copy it out.\r
+ // Get MAC address.\r
//\r
- if (NIC_ADDR_EQUAL (&Temp.NicAddr, NicAddr)) {\r
- Config = AllocatePool (Len);\r
-\r
- if (Config == NULL) {\r
- return NULL;\r
- }\r
-\r
- CopyMem (Config, Cur, Len);\r
- Ip4ConfigFixRouteTablePointer (&Config->Ip4Info);\r
- return Config;\r
+ AddrSize = 0;\r
+ Status = NetLibGetMacAddress (HandleBuffer[Index], &MacAddr, &AddrSize);\r
+ if (EFI_ERROR (Status)) {\r
+ Found = FALSE;\r
+ goto Exit;\r
}\r
\r
- Cur += Len;\r
+ if ((NicAddr->Len == AddrSize) && (CompareMem (NicAddr->MacAddr.Addr, MacAddr.Addr, AddrSize) == 0)) {\r
+ Found = TRUE;\r
+ goto Exit;\r
+ }\r
}\r
\r
- return NULL;\r
+Exit:\r
+ FreePool (HandleBuffer);\r
+ return Found;\r
}\r
\r
-\r
/**\r
- Modify the configuration parameter for the NIC in the variable.\r
- If Config is NULL, old configuration will be remove from the new\r
- variable. Otherwise, append it or replace the old one.\r
-\r
- @param Variable The IP4 variable to change\r
- @param NicAddr The interface to search\r
- @param Config The new configuration parameter (NULL to remove the old)\r
-\r
- @return The new IP4_CONFIG_VARIABLE variable if the new variable has at\r
- @return least one NIC configure and no EFI_OUT_OF_RESOURCES failure.\r
- @return Return NULL either because failed to locate memory for new variable\r
- @return or the only NIC configure is removed from the Variable.\r
+ Reclaim Ip4Config Variables for NIC which has been removed from the platform.\r
\r
**/\r
-IP4_CONFIG_VARIABLE *\r
-Ip4ConfigModifyVariable (\r
- IN IP4_CONFIG_VARIABLE *Variable, OPTIONAL\r
- IN NIC_ADDR *NicAddr,\r
- IN NIC_IP4_CONFIG_INFO *Config OPTIONAL\r
+VOID\r
+Ip4ConfigReclaimVariable (\r
+ VOID\r
)\r
{\r
- NIC_IP4_CONFIG_INFO Temp;\r
- NIC_IP4_CONFIG_INFO *Old;\r
- IP4_CONFIG_VARIABLE *NewVar;\r
- UINT32 Len;\r
- UINT32 TotalLen;\r
- UINT32 Count;\r
- UINT8 *Next;\r
- UINT8 *Cur;\r
- UINT32 Index;\r
-\r
- ASSERT ((Variable != NULL) || (Config != NULL));\r
+ EFI_STATUS Status;\r
+ UINTN VariableNameSize;\r
+ CHAR16 *VariableName;\r
+ CHAR16 *CurrentVariableName;\r
+ EFI_GUID VendorGuid;\r
+ UINTN VariableNameBufferSize;\r
+ NIC_IP4_CONFIG_INFO *NicConfig;\r
\r
//\r
- // Compute the total length\r
+ // Check whether we need perform reclaim.\r
//\r
- if (Variable != NULL) {\r
- //\r
- // Variable != NULL, then Config can be NULL or not. and so is\r
- // the Old. If old configure exists, it is removed from the\r
- // Variable. New configure is append to the variable.\r
- //\r
- //\r
- Count = Variable->Count;\r
- Cur = (UINT8 *)&Variable->ConfigInfo;\r
- TotalLen = Variable->Len;\r
+ if (mIp4ConfigVariableReclaimed) {\r
+ return;\r
+ }\r
+ mIp4ConfigVariableReclaimed = TRUE;\r
\r
- Old = Ip4ConfigFindNicVariable (Variable, NicAddr);\r
+ //\r
+ // Get all Ip4Config Variable.\r
+ //\r
+ VariableNameSize = sizeof (CHAR16);\r
+ VariableName = AllocateZeroPool (VariableNameSize);\r
+ VariableNameBufferSize = VariableNameSize;\r
+\r
+ while (TRUE) {\r
+ Status = gRT->GetNextVariableName (\r
+ &VariableNameSize,\r
+ VariableName,\r
+ &VendorGuid\r
+ );\r
\r
- if (Old != NULL) {\r
- TotalLen -= SIZEOF_NIC_IP4_CONFIG_INFO (Old);\r
- gBS->FreePool (Old);\r
+Check:\r
+ if (Status == EFI_BUFFER_TOO_SMALL) {\r
+ VariableName = ReallocatePool (VariableNameBufferSize, VariableNameSize, VariableName);\r
+ VariableNameBufferSize = VariableNameSize;\r
+ //\r
+ // Try again using the new buffer.\r
+ //\r
+ Status = gRT->GetNextVariableName (\r
+ &VariableNameSize,\r
+ VariableName,\r
+ &VendorGuid\r
+ );\r
}\r
\r
- if (Config != NULL) {\r
- TotalLen += SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // No more variable available, finish search.\r
+ //\r
+ break;\r
}\r
\r
//\r
- // Return NULL if the only NIC_IP4_CONFIG_INFO is being removed.\r
+ // Check variable GUID.\r
//\r
- if (TotalLen < sizeof (IP4_CONFIG_VARIABLE)) {\r
- return NULL;\r
+ if (!CompareGuid (&VendorGuid, &gEfiNicIp4ConfigVariableGuid)) {\r
+ continue;\r
}\r
\r
- } else {\r
- //\r
- // Variable == NULL and Config != NULL, Create a new variable with\r
- // this NIC configure.\r
- //\r
- Count = 0;\r
- Cur = NULL;\r
- TotalLen = sizeof (IP4_CONFIG_VARIABLE) - sizeof (NIC_IP4_CONFIG_INFO)\r
- + SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
- }\r
-\r
- ASSERT (TotalLen >= sizeof (IP4_CONFIG_VARIABLE));\r
-\r
- NewVar = AllocateZeroPool (TotalLen);\r
-\r
- if (NewVar == NULL) {\r
- return NULL;\r
- }\r
-\r
- NewVar->Len = TotalLen;\r
-\r
- //\r
- // Copy the other configure parameters from the old variable\r
- //\r
- Next = (UINT8 *)&NewVar->ConfigInfo;\r
-\r
- for (Index = 0; Index < Count; Index++) {\r
- CopyMem (&Temp, Cur, sizeof (NIC_IP4_CONFIG_INFO));\r
- Len = SIZEOF_NIC_IP4_CONFIG_INFO (&Temp);\r
-\r
- if (!NIC_ADDR_EQUAL (&Temp.NicAddr, NicAddr)) {\r
- CopyMem (Next, Cur, Len);\r
- Next += Len;\r
- NewVar->Count++;\r
+ GetVariable2 (VariableName, &gEfiNicIp4ConfigVariableGuid, (VOID**)&NicConfig, NULL);\r
+ if (NicConfig == NULL) {\r
+ break;\r
}\r
\r
- Cur += Len;\r
+ if (!Ip4ConfigIsNicExist (&NicConfig->NicAddr)) {\r
+ //\r
+ // No NIC found for this Ip4Config variable, remove it.\r
+ // Since we are in loop of GetNextVariableName(), we need move on to next\r
+ // Variable first and then delete current Variable.\r
+ //\r
+ CurrentVariableName = AllocateCopyPool (VariableNameSize, VariableName);\r
+ Status = gRT->GetNextVariableName (\r
+ &VariableNameSize,\r
+ VariableName,\r
+ &VendorGuid\r
+ );\r
+\r
+ gRT->SetVariable (\r
+ CurrentVariableName,\r
+ &gEfiNicIp4ConfigVariableGuid,\r
+ IP4_CONFIG_VARIABLE_ATTRIBUTES,\r
+ 0,\r
+ NULL\r
+ );\r
+ FreePool (CurrentVariableName);\r
+\r
+ //\r
+ // We already get next variable, go to check it.\r
+ //\r
+ goto Check;\r
+ }\r
}\r
\r
- //\r
- // Append the new configure if it isn't NULL.\r
- //\r
- Len = 0;\r
-\r
- if (Config != NULL) {\r
- Len = SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
+ FreePool (VariableName);\r
+}\r
\r
- CopyMem (Next, Config, Len);\r
- NewVar->Count++;\r
- }\r
+/**\r
+ Fix the RouteTable pointer in an EFI_IP4_IPCONFIG_DATA structure.\r
\r
- ASSERT (Next + Len == (UINT8 *) NewVar + TotalLen);\r
+ The pointer is set to be immediately follow the ConfigData if there're entries\r
+ in the RouteTable. Otherwise it is set to NULL.\r
\r
- NewVar->CheckSum = (UINT16) (~NetblockChecksum ((UINT8 *) NewVar, TotalLen));\r
- return NewVar;\r
-}\r
+ @param ConfigData The IP4 IP configure data.\r
\r
+**/\r
VOID\r
Ip4ConfigFixRouteTablePointer (\r
- IN EFI_IP4_IPCONFIG_DATA *ConfigData\r
+ IN OUT EFI_IP4_IPCONFIG_DATA *ConfigData\r
)\r
{\r
//\r
- // The memory used for route table entries must immediately follow \r
+ // The memory used for route table entries must immediately follow\r
// the ConfigData and be not packed.\r
//\r
if (ConfigData->RouteTableSize > 0) {\r