[edk2] [Patch 2/3] MdeModulePkg/Ip4Dxe: Support SetData interface to clear specific configuration

Jiaxin Wu posted 3 patches 7 years, 5 months ago
[edk2] [Patch 2/3] MdeModulePkg/Ip4Dxe: Support SetData interface to clear specific configuration
Posted by Jiaxin Wu 7 years, 5 months ago
UEFI Spec 2.7 adds the clarification on SetData interface usage to clear specific
individual data types. This patch is to support this feature.

Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
---
 .../Universal/Network/Ip4Dxe/Ip4Config2Impl.c      | 285 ++++++++++++++-------
 1 file changed, 190 insertions(+), 95 deletions(-)

diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
index 3e38085..26530e3 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Config2Impl.c
@@ -1239,63 +1239,127 @@ Ip4Config2SetManualAddress (
   EFI_STATUS                     Status;
   IP4_ADDR                       StationAddress;
   IP4_ADDR                       SubnetMask;
   VOID                           *Ptr;
   IP4_SERVICE                    *IpSb;
+  IP4_INTERFACE                  *IpIf;
+  IP4_ROUTE_TABLE                *RouteTable;
+
+  DataItem   = NULL;
+  Status     = EFI_SUCCESS;
+  Ptr        = NULL;
+  IpIf       = NULL;
+  RouteTable = NULL;
 
   IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
 
   ASSERT (Instance->DataItem[Ip4Config2DataTypeManualAddress].Status != EFI_NOT_READY);
 
-  if (((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0) || (DataSize == 0)) {
+  if ((DataSize != 0) && ((DataSize % sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS)) != 0)) {
     return EFI_BAD_BUFFER_SIZE;
   }
 
   if (Instance->Policy != Ip4Config2PolicyStatic) {
     return EFI_WRITE_PROTECTED;
   }
 
-  NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);
+  DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
 
-  StationAddress = EFI_NTOHL (NewAddress.Address);
-  SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);
+  if (Data != NULL && DataSize != 0) {
+    NewAddress = *((EFI_IP4_CONFIG2_MANUAL_ADDRESS *) Data);
 
-  //
-  // Check whether the StationAddress/SubnetMask pair is valid.
-  //
-  if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {
-    return EFI_INVALID_PARAMETER;
-  }
+    StationAddress = EFI_NTOHL (NewAddress.Address);
+    SubnetMask = EFI_NTOHL (NewAddress.SubnetMask);
 
-  //
-  // Store the new data, and init the DataItem status to EFI_NOT_READY because
-  // we may have an asynchronous configuration process.
-  //
-  Ptr = AllocateCopyPool (DataSize, Data);
-  if (Ptr == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
+    //
+    // Check whether the StationAddress/SubnetMask pair is valid.
+    //
+    if (!Ip4StationAddressValid (StationAddress, SubnetMask)) {
+      return EFI_INVALID_PARAMETER;
+    }
 
-  DataItem = &Instance->DataItem[Ip4Config2DataTypeManualAddress];
-  if (DataItem->Data.Ptr != NULL) {
-    FreePool (DataItem->Data.Ptr);
-  }
-  
-  DataItem->Data.Ptr = Ptr;
-  DataItem->DataSize = DataSize;
-  DataItem->Status   = EFI_NOT_READY;
+    //
+    // Store the new data, and init the DataItem status to EFI_NOT_READY because
+    // we may have an asynchronous configuration process.
+    //
+    Ptr = AllocateCopyPool (DataSize, Data);
+    if (Ptr == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
 
-  IpSb->Reconfig = TRUE;
-  Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);
+    if (DataItem->Data.Ptr != NULL) {
+      FreePool (DataItem->Data.Ptr);
+    }
+    
+    DataItem->Data.Ptr = Ptr;
+    DataItem->DataSize = DataSize;
+    DataItem->Status   = EFI_NOT_READY;
+
+    IpSb->Reconfig = TRUE;
+    Status = Ip4Config2SetDefaultAddr (IpSb, StationAddress, SubnetMask);
 
-  DataItem->Status = Status; 
+    DataItem->Status = Status;
 
-  if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) {
-    if (Ptr != NULL) {
-      FreePool (Ptr);
+    if (EFI_ERROR (DataItem->Status) && DataItem->Status != EFI_NOT_READY) {
+      if (Ptr != NULL) {
+        FreePool (Ptr);
+      }
+      DataItem->Data.Ptr = NULL; 
+    }
+  } else {
+    //
+    // DataSize is 0 and Data is NULL, clean up the manual address.
+    //
+    if (DataItem->Data.Ptr != NULL) {
+      FreePool (DataItem->Data.Ptr);
+    }
+    DataItem->Data.Ptr = NULL;
+    DataItem->DataSize = 0;
+    DataItem->Status   = EFI_NOT_FOUND;
+
+    //
+    // Free the default router table and Interface, clean up the assemble table.
+    //
+    if (IpSb->DefaultInterface != NULL) {
+      if (IpSb->DefaultRouteTable != NULL) {
+        Ip4FreeRouteTable (IpSb->DefaultRouteTable);
+        IpSb->DefaultRouteTable = NULL;    
+      }
+
+      Ip4CancelReceive (IpSb->DefaultInterface);
+
+      Ip4FreeInterface (IpSb->DefaultInterface, NULL);
+      IpSb->DefaultInterface = NULL;
+    }
+
+    Ip4CleanAssembleTable (&IpSb->Assemble);
+
+    //
+    // Create new default interface and route table.
+    //    
+    IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);
+    if (IpIf == NULL) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    RouteTable = Ip4CreateRouteTable ();
+    if (RouteTable == NULL) {
+      Ip4FreeInterface (IpIf, NULL);
+      return EFI_OUT_OF_RESOURCES;
+    }
+    
+    IpSb->DefaultInterface  = IpIf;
+    InsertHeadList (&IpSb->Interfaces, &IpIf->Link);
+    IpSb->DefaultRouteTable = RouteTable;
+    Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);
+
+    //
+    // Reset the State to unstarted. 
+    //
+    if (IpSb->State == IP4_SERVICE_CONFIGED || IpSb->State == IP4_SERVICE_STARTED) {
+      IpSb->State = IP4_SERVICE_UNSTARTED;
     }
-    DataItem->Data.Ptr = NULL; 
   }
 
   return Status;
 }
 
@@ -1340,98 +1404,114 @@ Ip4Config2SetGateway (
   UINTN                 NewGatewayCount;
   BOOLEAN               OneRemoved;
   BOOLEAN               OneAdded;
   VOID                  *Tmp;
 
-  if ((DataSize % sizeof (EFI_IPv4_ADDRESS) != 0) || (DataSize == 0)) {
+  OldGateway      = NULL;
+  NewGateway      = NULL;
+  OneRemoved      = FALSE;
+  OneAdded        = FALSE;
+  Tmp             = NULL;
+
+  if ((DataSize != 0) && (DataSize % sizeof (EFI_IPv4_ADDRESS) != 0)) {
     return EFI_BAD_BUFFER_SIZE;
   }
 
   if (Instance->Policy != Ip4Config2PolicyStatic) {
     return EFI_WRITE_PROTECTED;
   }
 
   IpSb = IP4_SERVICE_FROM_IP4_CONFIG2_INSTANCE (Instance);
 
-  NewGateway      = (EFI_IPv4_ADDRESS *) Data;
-  NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
-  for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
-    CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
-
-    if ((IpSb->DefaultInterface->SubnetMask != 0) && 
-        !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) {
-      return EFI_INVALID_PARAMETER;
-    }
-
-    for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {
-      if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) {
-        return EFI_INVALID_PARAMETER;
-      }
-    }
-  }
- 
-  DataItem = &Instance->DataItem[Ip4Config2DataTypeGateway];
+  DataItem        = &Instance->DataItem[Ip4Config2DataTypeGateway];
   OldGateway      = DataItem->Data.Gateway;
   OldGatewayCount = DataItem->DataSize / sizeof (EFI_IPv4_ADDRESS);
-  OneRemoved      = FALSE;
-  OneAdded        = FALSE;
-
-  if (NewGatewayCount != OldGatewayCount) {
-    Tmp = AllocatePool (DataSize);
-    if (Tmp == NULL) {
-      return EFI_OUT_OF_RESOURCES;
-    }
-  } else {
-    Tmp = NULL;
-  }
 
   for (Index1 = 0; Index1 < OldGatewayCount; Index1++) {
     //
-    // Remove this route entry.
+    // Remove the old route entry.
     //
     CopyMem (&Gateway, OldGateway + Index1, sizeof (IP4_ADDR));
     Ip4DelRoute (
       IpSb->DefaultRouteTable,
       IP4_ALLZERO_ADDRESS,
       IP4_ALLZERO_ADDRESS,
       NTOHL (Gateway)
       );
     OneRemoved = TRUE;
-
   }
 
-  for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
-    CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
-    Ip4AddRoute (
-      IpSb->DefaultRouteTable,
-      IP4_ALLZERO_ADDRESS,
-      IP4_ALLZERO_ADDRESS,
-      NTOHL (Gateway)
-      );    
-
-    OneAdded = TRUE;
-  }
+  if (Data != NULL && DataSize != 0) {
+    NewGateway      = (EFI_IPv4_ADDRESS *) Data;
+    NewGatewayCount = DataSize / sizeof (EFI_IPv4_ADDRESS);
+    for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
+      CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
 
+      if ((IpSb->DefaultInterface->SubnetMask != 0) && 
+          !NetIp4IsUnicast (NTOHL (Gateway), IpSb->DefaultInterface->SubnetMask)) {
+        return EFI_INVALID_PARAMETER;
+      }
 
-  if (!OneRemoved && !OneAdded) {
-    DataItem->Status = EFI_SUCCESS;
-    return EFI_ABORTED;
-  } else {
+      for (Index2 = Index1 + 1; Index2 < NewGatewayCount; Index2++) {
+        if (EFI_IP4_EQUAL (NewGateway + Index1, NewGateway + Index2)) {
+          return EFI_INVALID_PARAMETER;
+        }
+      }
+    }
 
-    if (Tmp != NULL) {
-      if (DataItem->Data.Ptr != NULL) {
-        FreePool (DataItem->Data.Ptr);
+    if (NewGatewayCount != OldGatewayCount) {
+      Tmp = AllocatePool (DataSize);
+      if (Tmp == NULL) {
+        return EFI_OUT_OF_RESOURCES;
       }
-      DataItem->Data.Ptr = Tmp;
+    } else {
+      Tmp = NULL;
     }
 
-    CopyMem (DataItem->Data.Ptr, Data, DataSize);
-    DataItem->DataSize = DataSize;
-    DataItem->Status   = EFI_SUCCESS;
-    return EFI_SUCCESS;
+    for (Index1 = 0; Index1 < NewGatewayCount; Index1++) {
+      //
+      // Add the new route entry.
+      //
+      CopyMem (&Gateway, NewGateway + Index1, sizeof (IP4_ADDR));
+      Ip4AddRoute (
+        IpSb->DefaultRouteTable,
+        IP4_ALLZERO_ADDRESS,
+        IP4_ALLZERO_ADDRESS,
+        NTOHL (Gateway)
+        );    
+
+      OneAdded = TRUE;
+    }
+
+    if (!OneRemoved && !OneAdded) {
+      DataItem->Status = EFI_SUCCESS;
+      return EFI_ABORTED;
+    } else {
+      if (Tmp != NULL) {
+        if (DataItem->Data.Ptr != NULL) {
+          FreePool (DataItem->Data.Ptr);
+        }
+        DataItem->Data.Ptr = Tmp;
+      }
+
+      CopyMem (DataItem->Data.Ptr, Data, DataSize);
+      DataItem->DataSize = DataSize;
+      DataItem->Status   = EFI_SUCCESS;
+    }
+  } else {
+    //
+    // DataSize is 0 and Data is NULL, clean up the Gateway address.
+    //
+    if (DataItem->Data.Ptr != NULL) {
+      FreePool (DataItem->Data.Ptr);
+    }
+    DataItem->Data.Ptr = NULL;
+    DataItem->DataSize = 0;
+    DataItem->Status   = EFI_NOT_FOUND;
   }
 
+  return EFI_SUCCESS;
 }
 
 /**
   The work function is to set the DNS server list for the EFI IPv4 network 
   stack running on the communication device that this EFI_IP4_CONFIG2_PROTOCOL 
@@ -1459,13 +1539,15 @@ Ip4Config2SetDnsServer (
   IN IP4_CONFIG2_INSTANCE *Instance,
   IN UINTN                DataSize,
   IN VOID                 *Data
   )
 {
-  IP4_CONFIG2_DATA_ITEM *Item;
+  EFI_STATUS                     Status;
+  IP4_CONFIG2_DATA_ITEM          *Item;
 
-  Item = NULL;
+  Status = EFI_SUCCESS;
+  Item   = NULL;
 
   if (Instance->Policy != Ip4Config2PolicyStatic) {
     return EFI_WRITE_PROTECTED;
   }
 
@@ -1473,11 +1555,25 @@ Ip4Config2SetDnsServer (
 
   if (DATA_ATTRIB_SET (Item->Attribute, DATA_ATTRIB_VOLATILE)) {
     REMOVE_DATA_ATTRIB (Item->Attribute, DATA_ATTRIB_VOLATILE);
   }
 
-  return Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);
+  if (Data != NULL && DataSize != 0) {
+    Status = Ip4Config2SetDnsServerWorker (Instance, DataSize, Data);
+  } else {
+    //
+    // DataSize is 0 and Data is NULL, clean up the DnsServer address. 
+    //
+    if (Item->Data.Ptr != NULL) {
+      FreePool (Item->Data.Ptr);
+    }
+    Item->Data.Ptr = NULL;
+    Item->DataSize = 0;
+    Item->Status   = EFI_NOT_FOUND;
+  }
+  
+  return Status;
 }
 
 /**
   Generate the operational state of the interface this IP4 config2 instance manages
   and output in EFI_IP4_CONFIG2_INTERFACE_INFO.
@@ -1552,13 +1648,12 @@ Ip4Config2OnDhcp4Event (
 
   @retval EFI_SUCCESS           The specified configuration data for the EFI IPv6
                                 network stack was set successfully.
   @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
                                 - This is NULL.
-                                - Data is NULL.
-                                - One or more fields in Data do not match the requirement of the
-                                  data type indicated by DataType.
+                                - One or more fields in Data and DataSize do not match the 
+                                  requirement of the data type indicated by DataType.
   @retval EFI_WRITE_PROTECTED   The specified configuration data is read-only or the specified
                                 configuration data cannot be set under the current policy.
   @retval EFI_ACCESS_DENIED     Another set operation on the specified configuration
                                 data is already in process.
   @retval EFI_NOT_READY         An asynchronous process was invoked to set the specified
@@ -1582,11 +1677,11 @@ EfiIp4Config2SetData (
   EFI_TPL              OldTpl;
   EFI_STATUS           Status;
   IP4_CONFIG2_INSTANCE *Instance;
   IP4_SERVICE          *IpSb;
 
-  if ((This == NULL) || (Data == NULL)) {
+  if ((This == NULL) || (Data == NULL && DataSize != 0) || (Data != NULL && DataSize == 0)) {
     return EFI_INVALID_PARAMETER;
   }
 
   if (DataType >= Ip4Config2DataTypeMaximum) {
     return EFI_UNSUPPORTED;
-- 
1.9.5.msysgit.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel