]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4ConfigDxe/NicIp4Variable.c
SourceLevelDebugPkg/SecPeiDebugAgentLib: Restore CPU interrupt state
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / NicIp4Variable.c
index d6e617eaa76ecd1a5d3aeb1f835bc2eb000832a9..f0e03af900bcc4037d3660bf1464cd3c44ccdd5d 100644 (file)
@@ -1,35 +1,21 @@
 /** @file\r
+  Routines used to operate the Ip4 configure variable.\r
 \r
-Copyright (c) 2006, 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
-\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
@@ -61,7 +47,7 @@ Ip4ConfigIsValid (
     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
@@ -73,7 +59,7 @@ Ip4ConfigIsValid (
       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
@@ -91,293 +77,243 @@ Ip4ConfigIsValid (
 \r
 \r
 /**\r
-  Read the ip4 configure variable from the EFI variable\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 = NetAllocatePool (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
-    NetFreePool (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
-    NetCopyMem (&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 = NetAllocatePool (Len);\r
-\r
-      if (Config == NULL) {\r
-        return NULL;\r
-      }\r
-\r
-      NetCopyMem (Config, Cur, Len);\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
-      NetFreePool (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 = NetAllocateZeroPool (TotalLen);\r
+    GetVariable2 (VariableName, &gEfiNicIp4ConfigVariableGuid, (VOID**)&NicConfig, NULL);\r
+    if (NicConfig == NULL) {\r
+      break;\r
+    }\r
 \r
-  if (NewVar == NULL) {\r
-    return NULL;\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
-  NewVar->Len = TotalLen;\r
-\r
-  //\r
-  // Copy the other configure parameters from the old variable\r
-  //\r
-  Next = (UINT8 *)&NewVar->ConfigInfo;\r
+  FreePool (VariableName);\r
+}\r
 \r
-  for (Index = 0; Index < Count; Index++) {\r
-    NetCopyMem (&Temp, Cur, sizeof (NIC_IP4_CONFIG_INFO));\r
-    Len = SIZEOF_NIC_IP4_CONFIG_INFO (&Temp);\r
+/**\r
+  Fix the RouteTable pointer in an EFI_IP4_IPCONFIG_DATA structure.\r
 \r
-    if (!NIC_ADDR_EQUAL (&Temp.NicAddr, NicAddr)) {\r
-      NetCopyMem (Next, Cur, Len);\r
-      Next += Len;\r
-      NewVar->Count++;\r
-    }\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
-    Cur += Len;\r
-  }\r
+  @param  ConfigData     The IP4 IP configure data.\r
 \r
+**/\r
+VOID\r
+Ip4ConfigFixRouteTablePointer (\r
+  IN OUT EFI_IP4_IPCONFIG_DATA  *ConfigData\r
+  )\r
+{\r
   //\r
-  // Append the new configure if it isn't NULL.\r
+  // The memory used for route table entries must immediately follow\r
+  // the ConfigData and be not packed.\r
   //\r
-  Len = 0;\r
-\r
-  if (Config != NULL) {\r
-    Len = SIZEOF_NIC_IP4_CONFIG_INFO (Config);\r
-\r
-    NetCopyMem (Next, Config, Len);\r
-    NewVar->Count++;\r
+  if (ConfigData->RouteTableSize > 0) {\r
+    ConfigData->RouteTable = (EFI_IP4_ROUTE_TABLE *) (ConfigData + 1);\r
+  } else {\r
+    ConfigData->RouteTable = NULL;\r
   }\r
-\r
-  ASSERT (Next + Len == (UINT8 *) NewVar + TotalLen);\r
-\r
-  NewVar->CheckSum = (UINT16) (~NetblockChecksum ((UINT8 *) NewVar, TotalLen));\r
-  return NewVar;\r
 }\r
+\r