]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
ShellPkg: Update ping/ifconfig library source code to consume Ip4Config2 protocol.
[mirror_edk2.git] / ShellPkg / Library / UefiShellNetwork1CommandsLib / Ifconfig.c
index fa00d6c6e9781ff57021d4dc23bdd64668745045..6977d6b67fdd28e09dc1dc19633205e38f6db2fc 100644 (file)
@@ -1,5 +1,5 @@
 /** @file\r
-  The implementation for ifcommand shell command.\r
+  The implementation for Shell command ifconfig based on IP4Config2 protocol.\r
 \r
   (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>\r
   Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>\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
 **/\r
 \r
 #include "UefiShellNetwork1CommandsLib.h"\r
 \r
-#define NIC_ITEM_CONFIG_SIZE   (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * MAX_IP4_CONFIG_IN_VARIABLE)\r
-#define EFI_IP4_TO_U32(EfiIpAddr)   (*(IP4_ADDR*)((EfiIpAddr).Addr))\r
-\r
-BOOLEAN                                 mIp4ConfigExist    = FALSE;\r
-STATIC EFI_HII_CONFIG_ROUTING_PROTOCOL  *mHiiConfigRouting = NULL;\r
+typedef enum {\r
+  IfConfigOpList     = 1,\r
+  IfConfigOpSet      = 2,\r
+  IfConfigOpClear    = 3\r
+} IFCONFIG_OPCODE;\r
+\r
+typedef enum {\r
+  VarCheckReserved      = -1,\r
+  VarCheckOk            = 0,\r
+  VarCheckDuplicate,\r
+  VarCheckConflict,\r
+  VarCheckUnknown,\r
+  VarCheckLackValue,\r
+  VarCheckOutOfMem\r
+} VAR_CHECK_CODE;\r
+\r
+typedef enum {\r
+  FlagTypeSingle         = 0,\r
+  FlagTypeNeedVar,\r
+  FlagTypeNeedSet,\r
+  FlagTypeSkipUnknown\r
+} VAR_CHECK_FLAG_TYPE;\r
+\r
+#define MACADDRMAXSIZE    32\r
+\r
+typedef struct _IFCONFIG_INTERFACE_CB {\r
+  EFI_HANDLE                                  NicHandle;\r
+  LIST_ENTRY                                  Link;\r
+  EFI_IP4_CONFIG2_PROTOCOL                    *IfCfg;\r
+  EFI_IP4_CONFIG2_INTERFACE_INFO              *IfInfo; \r
+  EFI_IP4_CONFIG2_POLICY                      Policy;\r
+  UINT32                                      DnsCnt;\r
+  EFI_IPv4_ADDRESS                            DnsAddr[1];\r
+} IFCONFIG_INTERFACE_CB;\r
+\r
+typedef struct _ARG_LIST ARG_LIST;\r
+\r
+struct _ARG_LIST {\r
+  ARG_LIST    *Next;\r
+  CHAR16      *Arg;\r
+};\r
+\r
+typedef struct _IFCONFIG4_PRIVATE_DATA {\r
+  LIST_ENTRY  IfList;\r
+\r
+  UINT32      OpCode;\r
+  CHAR16      *IfName;\r
+  ARG_LIST    *VarArg;\r
+} IFCONFIG_PRIVATE_DATA;\r
+\r
+typedef struct _VAR_CHECK_ITEM{\r
+  CHAR16                 *FlagStr;\r
+  UINT32                 FlagID;\r
+  UINT32                 ConflictMask;\r
+  VAR_CHECK_FLAG_TYPE    FlagType;\r
+} VAR_CHECK_ITEM;\r
+\r
+SHELL_PARAM_ITEM    mIfConfigCheckList[] = {\r
+  {\r
+    L"-b",\r
+    TypeFlag\r
+  },\r
+  {\r
+    L"-l",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-r",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-c",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-s",\r
+    TypeMaxValue\r
+  },\r
+  {\r
+    NULL,\r
+    TypeMax\r
+  },\r
+};\r
+\r
+VAR_CHECK_ITEM  mSetCheckList[] = {\r
+  {\r
+   L"static",\r
+    0x00000001,\r
+    0x00000001,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"dhcp",\r
+    0x00000002,\r
+    0x00000001,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    L"dns",\r
+    0x00000008,\r
+    0x00000004,\r
+    FlagTypeSingle\r
+  },\r
+  {\r
+    NULL,\r
+    0x0,\r
+    0x0,\r
+    FlagTypeSkipUnknown\r
+  },\r
+};\r
 \r
-STATIC CONST UINTN SecondsToNanoSeconds = 10000000;\r
-STATIC CONST CHAR16 DhcpString[5]       = L"DHCP";\r
-STATIC CONST CHAR16 StaticString[7]     = L"STATIC";\r
 STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";\r
 \r
-typedef struct {\r
-  LIST_ENTRY                  Link;\r
-  EFI_HANDLE                  Handle;\r
-  NIC_ADDR                    NicAddress;\r
-  CHAR16                      Name[IP4_NIC_NAME_LENGTH];\r
-  BOOLEAN                     MediaPresentSupported;\r
-  BOOLEAN                     MediaPresent;\r
-  EFI_IP4_CONFIG_PROTOCOL     *Ip4Config;\r
-  NIC_IP4_CONFIG_INFO         *ConfigInfo;\r
-} NIC_INFO;\r
-\r
-typedef struct {\r
-  EFI_IP_ADDRESS              DestIp;\r
-  EFI_MAC_ADDRESS             DestMac;\r
-  EFI_IP_ADDRESS              LocalIp;\r
-  EFI_MAC_ADDRESS             LocalMac;\r
-  UINT8                       MacLen;\r
-  EFI_EVENT                   OnResolved;\r
-  BOOLEAN                     Duplicate;\r
-} ARP_REQUEST;\r
-\r
-STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r
-  {L"-c",     TypeValue},\r
-  {L"-l",     TypeValue},\r
-  {L"-s",     TypeMaxValue},\r
-  {NULL,      TypeMax}\r
-  };\r
-\r
-STATIC LIST_ENTRY                  NicInfoList;\r
-STATIC BOOLEAN                     ArpResolved;\r
-STATIC BOOLEAN                     mTimeout;\r
-\r
 /**\r
-  Count the space delimited items in a string.\r
-\r
-  @param[in] String     A pointer to the string to count.\r
-\r
-  @return The number of space-delimited items.\r
-  @retval 0xFF an error occured.\r
-**/\r
-UINT8\r
-EFIAPI\r
-CountSubItems (\r
-  IN CONST CHAR16 *String\r
-  )\r
-{\r
-  CONST CHAR16  *Walker;\r
-  UINT8         Count;\r
-\r
-  if (String == NULL || *String == CHAR_NULL) {\r
-    return (0xFF);\r
-  }\r
+  Split a string with specified separator and save the substring to a list.\r
 \r
-  for (Walker = String, Count = 0 ; Walker != NULL && *Walker != CHAR_NULL ; Walker = (StrStr(Walker, L" ")==NULL?NULL:StrStr(Walker, L" ")+1), Count++);\r
-  return (Count);\r
-}\r
+  @param[in]    String       The pointer of the input string.\r
+  @param[in]    Separator    The specified separator.\r
 \r
-/**\r
-  Find the NIC_INFO by the specified nic name.\r
+  @return The pointer of headnode of ARG_LIST.\r
 \r
-  @param[in] Name     The pointer to the string containing the NIC name.\r
-  \r
-  @return The pointer to the NIC_INFO if there is a NIC_INFO named by Name.\r
-  @retval NULL  No NIC_INFO was found for Name.\r
 **/\r
-NIC_INFO*\r
-EFIAPI\r
-IfconfigFindNicByName (\r
-  IN CONST CHAR16           *Name\r
+ARG_LIST *\r
+SplitStrToList (\r
+  IN CONST CHAR16    *String,\r
+  IN CHAR16          Separator\r
   )\r
 {\r
-  LIST_ENTRY                *Entry;\r
-  LIST_ENTRY                *NextEntry;\r
-  NIC_INFO                  *Info;\r
-  CHAR16                    *TempString;\r
-\r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
-    Info = BASE_CR (Entry, NIC_INFO, Link);\r
-    TempString = (CHAR16*)Info->Name;\r
+  CHAR16      *Str;\r
+  CHAR16      *ArgStr;\r
+  ARG_LIST    *ArgList;\r
+  ARG_LIST    *ArgNode;\r
 \r
-    if (StringNoCaseCompare (&Name, &TempString) == 0) {\r
-      return Info;\r
-    }\r
+  if (*String == L'\0') {\r
+    return NULL;\r
   }\r
 \r
-  return NULL;\r
-}\r
-\r
-/**\r
-  Tests whether a child handle is a child device of the controller.\r
-\r
-  @param[in] ControllerHandle   A handle for a (parent) controller to test.\r
-  @param[in] ChildHandle        A child handle to test.\r
-  @param[in] ProtocolGuid       Supplies the protocol that the child controller\r
-                                opens on its parent controller.\r
-\r
-  @retval EFI_SUCCESS         ChildHandle is a child of the ControllerHandle.\r
-  @retval EFI_UNSUPPORTED     ChildHandle is not a child of the ControllerHandle.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-TestChildHandle (\r
-  IN CONST EFI_HANDLE       ControllerHandle,\r
-  IN CONST EFI_HANDLE       ChildHandle,\r
-  IN CONST EFI_GUID         *ProtocolGuid\r
-  )\r
-{\r
-  EFI_STATUS                            Status;\r
-  EFI_OPEN_PROTOCOL_INFORMATION_ENTRY   *OpenInfoBuffer;\r
-  UINTN                                 EntryCount;\r
-  UINTN                                 Index;\r
-\r
-  ASSERT (ProtocolGuid != NULL);\r
-\r
   //\r
-  // Retrieve the list of agents that are consuming the specific protocol\r
-  // on ControllerHandle.\r
+  // Copy the CONST string to a local copy.\r
   //\r
-  Status = gBS->OpenProtocolInformation (\r
-                 ControllerHandle,\r
-                 (EFI_GUID *) ProtocolGuid,\r
-                 &OpenInfoBuffer,\r
-                 &EntryCount\r
-                 );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_UNSUPPORTED;\r
-  }\r
+  Str = AllocateCopyPool (StrSize (String), String);\r
+  ASSERT (Str != NULL);\r
+  ArgStr  = Str;\r
 \r
   //\r
-  // Inspect if ChildHandle is one of the agents.\r
+  // init a node for the list head.\r
   //\r
-  Status = EFI_UNSUPPORTED;\r
-  for (Index = 0; Index < EntryCount; Index++) {\r
-    if ((OpenInfoBuffer[Index].ControllerHandle == ChildHandle) &&\r
-        (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {\r
-      Status = EFI_SUCCESS;\r
-      break;\r
-    }\r
-  }\r
-\r
-  FreePool (OpenInfoBuffer);\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Get the child handle of the NIC handle.\r
-\r
-  @param[in] Controller     Routing information: GUID.\r
-  @param[out] ChildHandle   Returned child handle.\r
-\r
-  @retval EFI_SUCCESS         Successfully to get child handle.\r
-**/\r
-EFI_STATUS \r
-GetChildHandle (\r
-  IN EFI_HANDLE         Controller,\r
-  OUT EFI_HANDLE        *ChildHandle\r
-  )\r
-{\r
-  EFI_STATUS                 Status;\r
-  EFI_HANDLE                 *Handles;\r
-  UINTN                      HandleCount;\r
-  UINTN                      Index;\r
-  EFI_DEVICE_PATH_PROTOCOL   *ChildDeviceDevicePath;\r
-  VENDOR_DEVICE_PATH         *VendorDeviceNode;\r
+  ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));\r
+  ASSERT (ArgNode != NULL);\r
+  ArgList = ArgNode;\r
 \r
   //\r
-  // Locate all EFI Hii Config Access protocols\r
+  // Split the local copy and save in the list node.\r
   //\r
-  Status = gBS->LocateHandleBuffer (\r
-                 ByProtocol,\r
-                 &gEfiHiiConfigAccessProtocolGuid,\r
-                 NULL,\r
-                 &HandleCount,\r
-                 &Handles\r
-                 );\r
-  if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = EFI_NOT_FOUND;\r
-\r
-  for (Index = 0; Index < HandleCount; Index++) {\r
-  \r
-    Status = TestChildHandle (Controller, Handles[Index], &gEfiManagedNetworkServiceBindingProtocolGuid);\r
-    if (!EFI_ERROR (Status)) {\r
-      //\r
-      // Get device path on the child handle\r
-      //\r
-      Status = gBS->HandleProtocol (\r
-                     Handles[Index],\r
-                     &gEfiDevicePathProtocolGuid,\r
-                     (VOID **) &ChildDeviceDevicePath\r
-                     );\r
-      \r
-      if (!EFI_ERROR (Status)) {\r
-        while (!IsDevicePathEnd (ChildDeviceDevicePath)) {\r
-          ChildDeviceDevicePath = NextDevicePathNode (ChildDeviceDevicePath);\r
-          //\r
-          // Parse one instance\r
-          //\r
-          if (ChildDeviceDevicePath->Type == HARDWARE_DEVICE_PATH && \r
-              ChildDeviceDevicePath->SubType == HW_VENDOR_DP) {\r
-            VendorDeviceNode = (VENDOR_DEVICE_PATH *) ChildDeviceDevicePath;\r
-            if (CompareMem (&VendorDeviceNode->Guid, &gEfiNicIp4ConfigVariableGuid, sizeof (EFI_GUID)) == 0) {\r
-              //\r
-              // Found item matched gEfiNicIp4ConfigVariableGuid\r
-              //\r
-              *ChildHandle = Handles[Index];\r
-              FreePool (Handles);\r
-              return EFI_SUCCESS;\r
-            }\r
-          }\r
-        }\r
-      }      \r
+  while (*Str != L'\0') {\r
+    if (*Str == Separator) {\r
+      *Str          = L'\0';\r
+      ArgNode->Arg  = ArgStr;\r
+      ArgStr        = Str + 1;\r
+      ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));\r
+      ASSERT (ArgNode->Next != NULL);\r
+      ArgNode = ArgNode->Next;\r
     }\r
+\r
+    Str++;\r
   }\r
 \r
-  FreePool (Handles);\r
-  return Status;  \r
+  ArgNode->Arg  = ArgStr;\r
+  ArgNode->Next = NULL;\r
+\r
+  return ArgList;\r
 }\r
 \r
 /**\r
-  Append OFFSET/WIDTH/VALUE items at the beginning of string.\r
-\r
-  @param[in, out]  String      The pointer to the string to append onto.\r
-  @param[in]       MaxLen      The max number of UNICODE char in String\r
-                               including the terminate NULL char.\r
-  @param[in]       Offset      Offset value.\r
-  @param[in]       Width       Width value.\r
-  @param[in]       Block       Point to data buffer.\r
-\r
-  @return The count of unicode character that were appended.\r
-**/\r
-UINTN\r
-EFIAPI\r
-AppendOffsetWidthValue (\r
-  IN OUT CHAR16               *String,\r
-  IN UINTN                    MaxLen,\r
-  IN UINTN                    Offset,\r
-  IN UINTN                    Width,\r
-  IN CONST UINT8              *Block\r
-  )\r
-\r
-{\r
-  CHAR16                      *OriString;\r
-\r
-  OriString = String;\r
-\r
-  StrnCpyS (String, MaxLen, L"&OFFSET=", 9);\r
-  String += StrLen (L"&OFFSET=");\r
-  String += UnicodeSPrint (String, 20, L"%x", Offset);\r
-\r
-  StrnCpyS (String, MaxLen, L"&WIDTH=", 8);\r
-  String += StrLen (L"&WIDTH=");\r
-  String += UnicodeSPrint (String, 20, L"%x", Width);\r
+  Check the correctness of input Args with '-s' option.\r
 \r
-  if (Block != NULL) {\r
-    StrnCpyS (String, MaxLen, L"&VALUE=", 8);\r
-    String += StrLen (L"&VALUE=");\r
-    while ((Width--) != 0) {\r
-      String += UnicodeSPrint (String, 20, L"%x", Block[Width]);\r
-    }\r
-  }\r
-  \r
-  return String - OriString;\r
-}\r
+  @param[in]    CheckList    The pointer of VAR_CHECK_ITEM array.\r
+  @param[in]    Name         The pointer of input arg.\r
+  @param[in]    Init         The switch to execute the check.\r
 \r
-/**\r
-  Converts the unicode character of the string from uppercase to lowercase.\r
-  This is a internal function.\r
+  @return   VarCheckOk          Valid parameter or Initialize check successfully.\r
+  @return   VarCheckDuplicate   Duplicated parameter happened.\r
+  @return   VarCheckConflict    Conflicted parameter happened\r
+  @return   VarCheckUnknown     Unknown parameter.\r
 \r
-  @param ConfigString  String to be converted\r
 **/\r
-CHAR16* \r
-EFIAPI\r
-HiiToLower (\r
-  IN CHAR16   *ConfigString\r
-  )\r
+VAR_CHECK_CODE\r
+IfConfigRetriveCheckListByName(\r
+  IN VAR_CHECK_ITEM    *CheckList,\r
+  IN CHAR16            *Name,\r
+  IN BOOLEAN           Init\r
+)\r
 {\r
-  CHAR16      *String;\r
-  BOOLEAN     Lower;\r
-\r
-  //\r
-  // Convert all hex digits in range [A-F] in the configuration header to [a-f]\r
-  //\r
-  for (String = ConfigString, Lower = FALSE; String != NULL && *String != L'\0'; String++) {\r
-    if (*String == L'=') {\r
-      Lower = TRUE;\r
-    } else if (*String == L'&') {\r
-      Lower = FALSE;\r
-    } else if (Lower && *String >= L'A' && *String <= L'F') {\r
-      *String = (CHAR16) (*String - L'A' + L'a');\r
-    }\r
+  STATIC UINT32     CheckDuplicate;\r
+  STATIC UINT32     CheckConflict;\r
+  VAR_CHECK_CODE    RtCode;\r
+  UINT32            Index;\r
+  VAR_CHECK_ITEM    Arg;\r
+\r
+  if (Init) {\r
+    CheckDuplicate = 0;\r
+    CheckConflict  = 0;\r
+    return VarCheckOk;\r
   }\r
 \r
-  return (ConfigString);\r
-}\r
-\r
-\r
-/**\r
-  Construct <ConfigHdr> using routing information GUID/NAME/PATH.\r
-\r
-  @param[in] Guid         Routing information: GUID.\r
-  @param[in] Name         Routing information: NAME.\r
-  @param[in] DriverHandle Driver handle which contains the routing information: PATH.\r
-\r
-  @retval NULL            An error occured.\r
-  @return                 The pointer to configHdr string.\r
-**/\r
-CHAR16 *\r
-EFIAPI\r
-ConstructConfigHdr (\r
-  IN CONST EFI_GUID          *Guid,\r
-  IN CONST CHAR16            *Name,\r
-  IN EFI_HANDLE              DriverHandle\r
-  )\r
-{\r
-  EFI_STATUS                 Status;\r
-  CHAR16                     *ConfigHdr;\r
-  UINTN                      ConfigHdrBufferSize;\r
-  EFI_DEVICE_PATH_PROTOCOL   *DevicePath;\r
-  CHAR16                     *String;\r
-  UINTN                      Index;\r
-  UINT8                      *Buffer;\r
-  UINTN                      DevicePathLength;\r
-  UINTN                      NameLength;\r
+  RtCode  = VarCheckOk;\r
+  Index   = 0;\r
+  Arg     = CheckList[Index];\r
 \r
   //\r
-  // Get the device path from handle installed EFI HII Config Access protocol\r
+  // Check the Duplicated/Conflicted/Unknown input Args.\r
   //\r
-  Status = gBS->HandleProtocol (\r
-                 DriverHandle,\r
-                 &gEfiDevicePathProtocolGuid,\r
-                 (VOID **) &DevicePath\r
-                 );\r
-  if (EFI_ERROR (Status)) {\r
-    return NULL;\r
-  }\r
+  while (Arg.FlagStr != NULL) {\r
+    if (StrCmp (Arg.FlagStr, Name) == 0) {\r
 \r
-  DevicePathLength = GetDevicePathSize (DevicePath);\r
-  NameLength = StrLen (Name);\r
-  ConfigHdrBufferSize = (5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathLength * 2 + 1) * sizeof (CHAR16);\r
-  ConfigHdr = AllocateZeroPool (ConfigHdrBufferSize);\r
-  if (ConfigHdr == NULL) {\r
-    return NULL;\r
-  } \r
+      if (CheckDuplicate & Arg.FlagID) {\r
+        RtCode = VarCheckDuplicate;\r
+        break;\r
+      }\r
 \r
-  String = ConfigHdr;\r
-  StrnCpyS (String, ConfigHdrBufferSize/sizeof(CHAR16), L"GUID=", 6);\r
-  String += StrLen (L"GUID=");\r
+      if (CheckConflict & Arg.ConflictMask) {\r
+        RtCode = VarCheckConflict;\r
+        break;\r
+      }\r
 \r
-  //\r
-  // Append Guid converted to <HexCh>32\r
-  //\r
-  for (Index = 0, Buffer = (UINT8 *)Guid; Index < sizeof (EFI_GUID); Index++) {\r
-    String += UnicodeSPrint (String, 6, L"%02x", *Buffer++);\r
-  }\r
+      CheckDuplicate |= Arg.FlagID;\r
+      CheckConflict  |= Arg.ConflictMask;\r
+      break;\r
+    }\r
 \r
-  //\r
-  // Append L"&NAME="\r
-  //\r
-  StrnCpyS (String, ConfigHdrBufferSize/sizeof(CHAR16), L"&NAME=", 7);\r
-  String += StrLen (L"&NAME=");\r
-  for (Index = 0; Index < NameLength ; Index++) {\r
-    String += UnicodeSPrint (String, 10, L"00%x", Name[Index]);\r
+    Arg = CheckList[++Index];\r
   }\r
-  \r
-  //\r
-  // Append L"&PATH="\r
-  //\r
-  StrnCpyS (String, ConfigHdrBufferSize/sizeof(CHAR16), L"&PATH=", 7);\r
-  String += StrLen (L"&PATH=");\r
-  for (Index = 0, Buffer = (UINT8 *) DevicePath; Index < DevicePathLength; Index++) {\r
-    String += UnicodeSPrint (String, 6, L"%02x", *Buffer++);\r
+\r
+  if (Arg.FlagStr == NULL) {\r
+    RtCode = VarCheckUnknown;\r
   }\r
 \r
-  return (HiiToLower(ConfigHdr));\r
+  return RtCode;\r
 }\r
 \r
 /**\r
-  Get network physical device NIC information.\r
+  The notify function of create event when performing a manual config.\r
 \r
-  @param[in] Handle         The network physical device handle.\r
-  @param[out] NicAddr       NIC information.\r
+  @param[in]    Event        The event this notify function registered to.\r
+  @param[in]    Context      Pointer to the context data registered to the event.\r
 \r
-  @retval EFI_SUCCESS         Get NIC information successfully.\r
-**/                  \r
-EFI_STATUS\r
+**/\r
+VOID\r
 EFIAPI\r
-IfConfigGetNicMacInfo (\r
-  IN  EFI_HANDLE                    Handle,\r
-  OUT NIC_ADDR                      *NicAddr\r
-  )    \r
+IfConfigManualAddressNotify (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_HANDLE                    MnpHandle;\r
-  EFI_SIMPLE_NETWORK_MODE       SnpMode;\r
-  EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;\r
-\r
-  MnpHandle = NULL;\r
-  Mnp       = NULL;\r
-\r
-  Status = NetLibCreateServiceChild (\r
-             Handle,\r
-             gImageHandle, \r
-             &gEfiManagedNetworkServiceBindingProtocolGuid,\r
-             &MnpHandle\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  Status = gBS->HandleProtocol (\r
-                  MnpHandle,\r
-                  &gEfiManagedNetworkProtocolGuid,\r
-                  (VOID **) &Mnp\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
-\r
-  Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r
-  if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
-    goto ON_ERROR;\r
-  }\r
\r
-  NicAddr->Type    = (UINT16) SnpMode.IfType;\r
-  NicAddr->Len     = (UINT8) SnpMode.HwAddressSize;\r
-  CopyMem (&NicAddr->MacAddr, &SnpMode.CurrentAddress, NicAddr->Len);\r
-\r
-ON_ERROR:\r
-\r
-  NetLibDestroyServiceChild (\r
-    Handle,\r
-    gImageHandle, \r
-    &gEfiManagedNetworkServiceBindingProtocolGuid,\r
-    MnpHandle\r
-    );\r
-\r
-  return Status;\r
-\r
+  *((BOOLEAN *) Context) = TRUE;\r
 }\r
 \r
+\r
 /**\r
-  Get network physical device NIC information.\r
+  Print MAC address.\r
 \r
-  @param[in] Handle         The network physical device handle.\r
-  @param[out] MediaPresentSupported\r
-                            Upon successful return, TRUE is media present \r
-                            is supported.  FALSE otherwise.\r
-  @param[out] MediaPresent  Upon successful return, TRUE is media present \r
-                            is enabled.  FALSE otherwise.\r
+  @param[in]    Node    The pointer of MAC address buffer.\r
+  @param[in]    Size    The size of MAC address buffer.\r
 \r
-  @retval EFI_SUCCESS       The operation was successful.\r
 **/\r
-EFI_STATUS\r
-EFIAPI\r
-IfConfigGetNicMediaStatus (\r
-  IN  EFI_HANDLE                    Handle,\r
-  OUT BOOLEAN                       *MediaPresentSupported,\r
-  OUT BOOLEAN                       *MediaPresent\r
-  )    \r
-                  \r
+VOID\r
+IfConfigPrintMacAddr (\r
+  IN UINT8     *Node,\r
+  IN UINT32    Size\r
+  )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_HANDLE                    MnpHandle;\r
-  EFI_SIMPLE_NETWORK_MODE       SnpMode;\r
-  EFI_MANAGED_NETWORK_PROTOCOL  *Mnp;\r
-\r
-  MnpHandle = NULL;\r
-  Mnp       = NULL;\r
-\r
-  Status = NetLibCreateServiceChild (\r
-             Handle,\r
-             gImageHandle, \r
-             &gEfiManagedNetworkServiceBindingProtocolGuid,\r
-             &MnpHandle\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  UINTN    Index;\r
 \r
-  Status = gBS->HandleProtocol (\r
-                  MnpHandle,\r
-                  &gEfiManagedNetworkProtocolGuid,\r
-                  (VOID **) &Mnp\r
-                  );\r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
+  ASSERT (Size <= MACADDRMAXSIZE);\r
 \r
-  Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r
-  if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r
-    goto ON_ERROR;\r
+  for (Index = 0; Index < Size; Index++) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_BODY), gShellNetwork1HiiHandle, Node[Index]);\r
+    if (Index + 1 < Size) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_COLON), gShellNetwork1HiiHandle);\r
+    }\r
   }\r
\r
-  *MediaPresentSupported = SnpMode.MediaPresentSupported;\r
-  *MediaPresent = SnpMode.MediaPresent;\r
 \r
-ON_ERROR:\r
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);\r
+}\r
 \r
-  NetLibDestroyServiceChild (\r
-    Handle,\r
-    gImageHandle, \r
-    &gEfiManagedNetworkServiceBindingProtocolGuid,\r
-    MnpHandle\r
-    );\r
 \r
-  return Status;\r
+/**\r
+  The get current status of all handles.\r
 \r
-}\r
+  @param[in]   IfName         The pointer of IfName(interface name).\r
+  @param[in]   IfList         The pointer of IfList(interface list).\r
 \r
-/**\r
-  Get all Nic's information through HII service.\r
+  @retval EFI_SUCCESS    The get status processed successfully.\r
+  @retval others         The get status process failed.\r
 \r
-  @retval EFI_SUCCESS         All the nic information is collected.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-IfconfigGetAllNicInfoByHii (\r
-  VOID\r
+IfConfigGetInterfaceInfo (\r
+  IN CHAR16        *IfName,\r
+  IN LIST_ENTRY    *IfList\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_HANDLE                    *Handles;\r
-  UINTN                         HandleCount;\r
-  CHAR16                        *ConfigResp;\r
-  UINTN                         ConfigRespBufferSize;\r
-  CHAR16                        *ConfigHdr;\r
-  UINTN                         Index;\r
-  CHAR16                        *AccessProgress;\r
-  CHAR16                        *AccessResults;\r
-  UINTN                         BufferSize;\r
-  NIC_INFO                      *NicInfo;\r
-  NIC_IP4_CONFIG_INFO           *NicConfigRequest;\r
-  NIC_IP4_CONFIG_INFO           *NicConfig;\r
-  CHAR16                        *String;\r
-  UINTN                         Length;\r
-  UINTN                         Offset;\r
-  EFI_HANDLE                    ChildHandle;\r
-\r
-  AccessResults    = NULL;\r
-  ConfigHdr        = NULL;\r
-  ConfigResp       = NULL;\r
-  NicConfigRequest = NULL;\r
-  NicInfo          = NULL;\r
-\r
-  InitializeListHead (&NicInfoList);\r
+  EFI_STATUS                       Status;\r
+  UINTN                            HandleIndex;\r
+  UINTN                            HandleNum;\r
+  EFI_HANDLE                       *HandleBuffer;\r
+  EFI_IP4_CONFIG2_PROTOCOL         *Ip4Cfg2;\r
+  EFI_IP4_CONFIG2_INTERFACE_INFO   *IfInfo;\r
+  IFCONFIG_INTERFACE_CB            *IfCb;\r
+  UINTN                            DataSize;\r
 \r
-  //\r
-  // Check if HII Config Routing protocol available.\r
-  //\r
-  Status = gBS->LocateProtocol (\r
-                &gEfiHiiConfigRoutingProtocolGuid,\r
-                NULL,\r
-                (VOID**)&mHiiConfigRouting\r
-                );\r
-  if (EFI_ERROR (Status)) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
+  HandleBuffer = NULL;\r
+  HandleNum    = 0;\r
+\r
+  IfInfo       = NULL;\r
+  IfCb         = NULL;\r
 \r
   //\r
-  // Locate all network device handles\r
+  // Locate all the handles with ip4 service binding protocol.\r
   //\r
   Status = gBS->LocateHandleBuffer (\r
-                 ByProtocol,\r
-                 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
-                 NULL,\r
-                 &HandleCount,\r
-                 &Handles\r
+                  ByProtocol,\r
+                  &gEfiIp4ServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  &HandleNum,\r
+                  &HandleBuffer\r
                  );\r
-  if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
-    return EFI_NOT_FOUND;\r
+  if (EFI_ERROR (Status) || (HandleNum == 0)) {\r
+    return EFI_ABORTED;\r
   }\r
 \r
-  for (Index = 0; Index < HandleCount; Index++) {\r
-    Status = GetChildHandle (Handles[Index], &ChildHandle);\r
+  //\r
+  // Enumerate all handles that installed with ip4 service binding protocol.\r
+  //\r
+  for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
+    IfCb      = NULL;\r
+    IfInfo    = NULL;\r
+    DataSize  = 0;\r
+\r
+    //\r
+    // Ip4config protocol and ip4 service binding protocol are installed\r
+    // on the same handle.\r
+    //\r
+    ASSERT (HandleBuffer != NULL);\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[HandleIndex],\r
+                    &gEfiIp4Config2ProtocolGuid,\r
+                    (VOID **) &Ip4Cfg2\r
+                    );\r
+\r
     if (EFI_ERROR (Status)) {\r
-      //\r
-      // If failed to get Child handle, try NIC controller handle for back-compatibility.\r
-      //\r
-      ChildHandle = Handles[Index];\r
+      goto ON_ERROR;\r
     }\r
+    \r
     //\r
-    // Construct configuration request string header\r
+    // Get the interface information size.\r
     //\r
-    ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle);\r
-    if (ConfigHdr != NULL) {\r
-      Length = StrLen (ConfigHdr);\r
-    } else {\r
-      Length = 0;\r
+    Status = Ip4Cfg2->GetData (\r
+                       Ip4Cfg2,\r
+                       Ip4Config2DataTypeInterfaceInfo,\r
+                       &DataSize,\r
+                       NULL\r
+                       );\r
+\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      goto ON_ERROR;\r
     }\r
-    ConfigRespBufferSize = (Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16);\r
-    ConfigResp = AllocateZeroPool (ConfigRespBufferSize);\r
-    if (ConfigResp == NULL) {\r
+\r
+    IfInfo = AllocateZeroPool (DataSize);\r
+\r
+    if (IfInfo == NULL) {\r
       Status = EFI_OUT_OF_RESOURCES;\r
       goto ON_ERROR;\r
     }\r
-    if (ConfigHdr != NULL) {\r
-      StrnCpyS (ConfigResp, ConfigRespBufferSize/sizeof(CHAR16), ConfigHdr, Length + NIC_ITEM_CONFIG_SIZE * 2 + 100 - 1);\r
-    }\r
\r
+    \r
     //\r
-    // Append OFFSET/WIDTH pair\r
+    // Get the interface info.\r
     //\r
-    String = ConfigResp + Length;\r
-    Offset = 0;\r
-    AppendOffsetWidthValue (String, \r
-                            ConfigRespBufferSize/sizeof(CHAR16) - Length, \r
-                            Offset, \r
-                            NIC_ITEM_CONFIG_SIZE, \r
-                            NULL\r
-                            );\r
+    Status = Ip4Cfg2->GetData (\r
+                       Ip4Cfg2,\r
+                       Ip4Config2DataTypeInterfaceInfo,\r
+                       &DataSize,\r
+                       IfInfo\r
+                       );\r
 \r
-    NicInfo = AllocateZeroPool (sizeof (NIC_INFO));\r
-    if (NicInfo == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
+    if (EFI_ERROR (Status)) {\r
       goto ON_ERROR;\r
     }\r
-    NicInfo->Handle       = Handles[Index];\r
-\r
+    \r
     //\r
-    // Get network physical devcie MAC information\r
+    // Check the interface name if required.\r
     //\r
-    IfConfigGetNicMacInfo (Handles[Index], &NicInfo->NicAddress);\r
-    if (NicInfo->NicAddress.Type == NET_IFTYPE_ETHERNET) {\r
-      UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"eth%d", Index);\r
-    } else {\r
-      UnicodeSPrint (NicInfo->Name, IP4_NIC_NAME_LENGTH, L"unk%d", Index);\r
+    if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {\r
+      FreePool (IfInfo);\r
+      continue;\r
     }\r
 \r
+    DataSize = 0;\r
+    \r
     //\r
-    // Get media status\r
+    // Get the size of dns server list.\r
     //\r
-    IfConfigGetNicMediaStatus (Handles[Index], &NicInfo->MediaPresentSupported, &NicInfo->MediaPresent);\r
+    Status = Ip4Cfg2->GetData (\r
+                       Ip4Cfg2,\r
+                       Ip4Config2DataTypeDnsServer,\r
+                       &DataSize,\r
+                       NULL\r
+                       );\r
+\r
+    if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    IfCb = AllocateZeroPool (sizeof (IFCONFIG_INTERFACE_CB) + DataSize);\r
 \r
-    NicConfigRequest = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
-    if (NicConfigRequest == NULL) {\r
+    if (IfCb == NULL) {\r
       Status = EFI_OUT_OF_RESOURCES;\r
       goto ON_ERROR;\r
     }\r
 \r
+    IfCb->NicHandle = HandleBuffer[HandleIndex];\r
+    IfCb->IfInfo    = IfInfo;\r
+    IfCb->IfCfg     = Ip4Cfg2;\r
+    IfCb->DnsCnt    = (UINT32) (DataSize / sizeof (EFI_IPv4_ADDRESS));\r
+\r
     //\r
-    // Get network parameters by HII service\r
+    // Get the dns server list if has.\r
     //\r
-    Status = mHiiConfigRouting->ExtractConfig (\r
-                                  mHiiConfigRouting,\r
-                                  ConfigResp,\r
-                                  &AccessProgress,\r
-                                  &AccessResults\r
-                                  );\r
-    if (!EFI_ERROR (Status)) {\r
-      BufferSize = NIC_ITEM_CONFIG_SIZE;\r
-      Status = mHiiConfigRouting->ConfigToBlock (\r
-                                    mHiiConfigRouting,\r
-                                    AccessResults,\r
-                                    (UINT8 *) NicConfigRequest,\r
-                                    &BufferSize,\r
-                                    &AccessProgress\r
-                                    );\r
-      if (!EFI_ERROR (Status)) {\r
-        BufferSize = sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * NicConfigRequest->Ip4Info.RouteTableSize;\r
-        NicConfig = AllocateZeroPool (BufferSize);\r
-        if (NicConfig == NULL) {\r
-          Status = EFI_OUT_OF_RESOURCES;\r
-          goto ON_ERROR;\r
-        }\r
-        CopyMem (NicConfig, NicConfigRequest, BufferSize);\r
-\r
-        //\r
-        // If succeeds to get NIC configuration, fix up routetable pointer.\r
-        //\r
-        NicConfig->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (&NicConfig->Ip4Info + 1);\r
-        NicInfo->ConfigInfo   = NicConfig;\r
-\r
-      } else {\r
-        NicInfo->ConfigInfo   = NULL;\r
+    if (DataSize > 0) {\r
+      Status = Ip4Cfg2->GetData (\r
+                         Ip4Cfg2,\r
+                         Ip4Config2DataTypeDnsServer,\r
+                         &DataSize,\r
+                         IfCb->DnsAddr\r
+                         );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_ERROR;\r
       }\r
-\r
-      FreePool (AccessResults);\r
-\r
-    } else {\r
-      NicInfo->ConfigInfo   = NULL;\r
     }\r
 \r
     //\r
-    // Add the Nic's info to the global NicInfoList.\r
+    // Get the config policy.\r
     //\r
-    InsertTailList (&NicInfoList, &NicInfo->Link);\r
+    DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);\r
+    Status   = Ip4Cfg2->GetData (\r
+                         Ip4Cfg2,\r
+                         Ip4Config2DataTypePolicy,\r
+                         &DataSize,\r
+                         &IfCb->Policy\r
+                         );\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    InsertTailList (IfList, &IfCb->Link);\r
 \r
-    FreePool (NicConfigRequest);\r
-    FreePool (ConfigResp);\r
-    FreePool (ConfigHdr);\r
+    if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {\r
+      //\r
+      // Only need the appointed interface, keep the allocated buffer.\r
+      //\r
+      IfCb   = NULL;\r
+      IfInfo = NULL;\r
+      break;\r
+    }\r
   }\r
 \r
-  FreePool (Handles);\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
 \r
   return EFI_SUCCESS;\r
\r
+\r
 ON_ERROR:\r
-  if (AccessResults != NULL) {\r
-    FreePool (AccessResults);\r
-  }\r
-  if (NicConfigRequest != NULL) {\r
-    FreePool (NicConfigRequest);\r
-  }\r
-  if (NicInfo != NULL) {\r
-    FreePool (NicInfo);\r
-  }\r
-  if (ConfigResp != NULL) {\r
-    FreePool (ConfigResp);\r
-  }\r
-  if (ConfigHdr != NULL) {\r
-    FreePool (ConfigHdr);\r
+\r
+  if (IfInfo != NULL) {\r
+    FreePool (IfInfo);\r
   }\r
 \r
-  FreePool (Handles);\r
+  if (IfCb != NULL) {\r
+    FreePool (IfCb);\r
+  }\r
 \r
   return Status;\r
 }\r
 \r
 /**\r
-  Set the address for the specified nic by HII service.\r
+  The list process of the ifconfig command.\r
 \r
-  @param[in] NicInfo    A pointer to the NIC_INFO of the Nic to be configured.\r
-  @param[in] Config     The command line arguments for the set operation.\r
+  @param[in]   IfList    The pointer of IfList(interface list).\r
+\r
+  @retval EFI_SUCCESS    The ifconfig command list processed successfully.\r
+  @retval others         The ifconfig command list process failed.\r
 \r
-  @retval EFI_SUCCESS         The address set operation is done.\r
 **/\r
-SHELL_STATUS\r
-EFIAPI\r
-IfconfigSetNicAddrByHii (\r
-  IN CONST NIC_INFO                 *NicInfo,\r
-  IN CONST NIC_IP4_CONFIG_INFO      *Config\r
+EFI_STATUS\r
+IfConfigShowInterfaceInfo (\r
+  IN LIST_ENTRY    *IfList\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  SHELL_STATUS                  ShellStatus;\r
-  NIC_IP4_CONFIG_INFO           *NicConfig;\r
-  CHAR16                        *ConfigResp;\r
-  UINTN                         ConfigRespBufferSize;\r
-  CHAR16                        *ConfigHdr;\r
-  CHAR16                        *AccessProgress;\r
-  CHAR16                        *AccessResults;\r
-  CHAR16                        *String;\r
-  UINTN                         Length;\r
-  UINTN                         Offset;\r
-  EFI_HANDLE                    ChildHandle;\r
-\r
-  AccessResults  = NULL;\r
-  ConfigHdr      = NULL;\r
-  ConfigResp     = NULL;\r
-  NicConfig      = NULL;\r
-  ShellStatus    = SHELL_SUCCESS;\r
-\r
-  Status = GetChildHandle (NicInfo->Handle, &ChildHandle);\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // If failed to get Child handle, try NIC controller handle for back-compatibility\r
-    //\r
-    ChildHandle = NicInfo->Handle;\r
-  }\r
-  //\r
-  // Construct config request string header\r
-  //\r
-  ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle);\r
-  if (ConfigHdr != NULL) {\r
-    Length = StrLen (ConfigHdr);\r
-  } else {\r
-    ShellStatus = SHELL_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-  ConfigRespBufferSize = (Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16);\r
-  ConfigResp = AllocateZeroPool (ConfigRespBufferSize);\r
-  if (ConfigResp == NULL) {\r
-    ShellStatus = SHELL_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
-  if (ConfigHdr != NULL) {\r
-    StrnCpyS (ConfigResp, ConfigRespBufferSize/sizeof(CHAR16), ConfigHdr, Length + NIC_ITEM_CONFIG_SIZE * 2 + 100 - 1);\r
-  }\r
+  EFI_STATUS                Status;\r
+  LIST_ENTRY                *Entry;\r
+  LIST_ENTRY                *Next;\r
+  IFCONFIG_INTERFACE_CB     *IfCb;\r
+  EFI_IPv4_ADDRESS          Gateway;\r
+  UINT32                    Index;\r
 \r
-  NicConfig = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
-  if (NicConfig == NULL) {\r
-    ShellStatus = SHELL_OUT_OF_RESOURCES;\r
-    goto ON_EXIT;\r
-  }\r
+  Status = EFI_SUCCESS;\r
 \r
-  if (Config != NULL) {\r
-    CopyMem (NicConfig, Config, sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * Config->Ip4Info.RouteTableSize);\r
+  if (IsListEmpty (IfList)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);\r
   }\r
 \r
   //\r
-  // Append OFFSET/WIDTH pair\r
+  // Go through the interface list.\r
   //\r
-  String = ConfigResp + Length;\r
-  Offset = 0;\r
-  AppendOffsetWidthValue (String, \r
-                          ConfigRespBufferSize/sizeof(CHAR16) - Length,\r
-                          Offset, \r
-                          NIC_ITEM_CONFIG_SIZE, \r
-                          NULL\r
-                          );\r
+  NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {\r
+    IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);\r
 \r
-  //\r
-  // Call HII helper function to generate configuration string\r
-  //\r
-  Status = mHiiConfigRouting->BlockToConfig (\r
-                                mHiiConfigRouting,\r
-                                ConfigResp,\r
-                                (UINT8 *) NicConfig,\r
-                                NIC_ITEM_CONFIG_SIZE,\r
-                                &AccessResults,\r
-                                &AccessProgress\r
-                                );\r
-  if (EFI_ERROR (Status)) {\r
-    ShellStatus = SHELL_NOT_FOUND;\r
-    goto ON_EXIT;\r
-  }\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);\r
 \r
-  //\r
-  // Set IP setting by HII servie\r
-  //\r
-  Status = mHiiConfigRouting->RouteConfig (\r
-                                mHiiConfigRouting,\r
-                                AccessResults,\r
-                                &AccessProgress\r
-                                );\r
-  if (EFI_ERROR(Status)) {\r
-    ShellStatus = SHELL_ACCESS_DENIED;\r
-  }\r
+    //\r
+    // Print interface name.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IF_NAME), gShellNetwork1HiiHandle, IfCb->IfInfo->Name);\r
 \r
-ON_EXIT:\r
-  SHELL_FREE_NON_NULL(AccessResults);\r
-  SHELL_FREE_NON_NULL(NicConfig);\r
-  SHELL_FREE_NON_NULL(ConfigResp);\r
-  SHELL_FREE_NON_NULL(ConfigHdr);\r
+    //\r
+    // Print interface config policy.\r
+    //\r
+    if (IfCb->Policy == Ip4Config2PolicyDhcp) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_DHCP), gShellNetwork1HiiHandle);\r
+    } else {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_MAN), gShellNetwork1HiiHandle);\r
+    }\r
 \r
-  return ShellStatus;\r
-}\r
+    //\r
+    // Print mac address of the interface.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_HEAD), gShellNetwork1HiiHandle);\r
 \r
-/**\r
-  The callback function for the Arp address resolved event.\r
+    IfConfigPrintMacAddr (\r
+      IfCb->IfInfo->HwAddress.Addr,\r
+      IfCb->IfInfo->HwAddressSize\r
+      );\r
 \r
-  @param[in] Event    The event this function is registered to.\r
-  @param[in] Context  The context registered to the event.\r
-**/\r
-VOID\r
-EFIAPI\r
-IfconfigOnArpResolved (\r
-  IN EFI_EVENT                  Event,\r
-  IN VOID                       *Context\r
-  )\r
-{\r
-  ARP_REQUEST                   *Request;\r
-  UINT8                         Index;\r
+    //\r
+    // Print IPv4 address list of the interface.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_HEAD), gShellNetwork1HiiHandle);\r
 \r
-  Request = (ARP_REQUEST *) Context;\r
-  ASSERT (Request != NULL);\r
+    ShellPrintHiiEx(\r
+      -1, \r
+      -1, \r
+      NULL,\r
+      STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY), \r
+      gShellNetwork1HiiHandle,\r
+      (UINTN)IfCb->IfInfo->StationAddress.Addr[0],\r
+      (UINTN)IfCb->IfInfo->StationAddress.Addr[1],\r
+      (UINTN)IfCb->IfInfo->StationAddress.Addr[2],\r
+      (UINTN)IfCb->IfInfo->StationAddress.Addr[3]\r
+      );\r
+\r
+    //\r
+    // Print subnet mask list of the interface.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_SUBNET_MASK_HEAD), gShellNetwork1HiiHandle);\r
 \r
-  Request->Duplicate = FALSE;\r
-  \r
-  if (0 == CompareMem (&Request->LocalMac, &Request->DestMac, Request->MacLen)) {\r
     ShellPrintHiiEx(\r
       -1, \r
       -1, \r
       NULL,\r
-      STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-      gShellNetwork1HiiHandle, \r
-      L"Already Configured",\r
-      (UINTN)Request->DestIp.v4.Addr[0],\r
-      (UINTN)Request->DestIp.v4.Addr[1],\r
-      (UINTN)Request->DestIp.v4.Addr[2],\r
-      (UINTN)Request->DestIp.v4.Addr[3]\r
+      STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY), \r
+      gShellNetwork1HiiHandle,\r
+      (UINTN)IfCb->IfInfo->SubnetMask.Addr[0],\r
+      (UINTN)IfCb->IfInfo->SubnetMask.Addr[1],\r
+      (UINTN)IfCb->IfInfo->SubnetMask.Addr[2],\r
+      (UINTN)IfCb->IfInfo->SubnetMask.Addr[3]\r
       );\r
-    ArpResolved = TRUE;\r
-    return;\r
-  }\r
-  \r
-  for (Index = 0; Index < Request->MacLen; Index++) {\r
-    if (Request->DestMac.Addr[Index] != 0) {\r
-      Request->Duplicate = TRUE;\r
-    }\r
-  }\r
 \r
-  if (Request->Duplicate) {\r
+    //\r
+    // Print default gateway of the interface.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_GATEWAY_HEAD), gShellNetwork1HiiHandle);\r
+\r
+    ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));\r
+    \r
+    for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {\r
+      if ((CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&\r
+          (CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetMask   , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){\r
+        CopyMem (&Gateway, &IfCb->IfInfo->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
+      }\r
+    }    \r
+\r
     ShellPrintHiiEx(\r
-    -1,\r
-    -1,\r
-    NULL,\r
-    STRING_TOKEN(STR_IFCONFIG_CONF_IP_ADDR), \r
-    gShellNetwork1HiiHandle, \r
-    (UINTN)Request->DestMac.Addr[0], \r
-    (UINTN)Request->DestMac.Addr[1], \r
-    (UINTN)Request->DestMac.Addr[2],\r
-    (UINTN)Request->DestMac.Addr[3], \r
-    (UINTN)Request->DestMac.Addr[4], \r
-    (UINTN)Request->DestMac.Addr[5]\r
-    );    \r
+      -1, \r
+      -1, \r
+      NULL,\r
+      STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY), \r
+      gShellNetwork1HiiHandle,\r
+      (UINTN)Gateway.Addr[0],\r
+      (UINTN)Gateway.Addr[1],\r
+      (UINTN)Gateway.Addr[2],\r
+      (UINTN)Gateway.Addr[3]\r
+      );\r
+      \r
+    //\r
+    // Print route table entry.\r
+    //\r
+    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, IfCb->IfInfo->RouteTableSize);\r
+\r
+    for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {\r
+      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);\r
+\r
+      ShellPrintHiiEx(\r
+        -1, \r
+        -1, \r
+        NULL,\r
+        STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
+        gShellNetwork1HiiHandle, \r
+        L"Subnet ",\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[0],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[1],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[2],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[3]\r
+        );\r
+\r
+      ShellPrintHiiEx(\r
+        -1, \r
+        -1, \r
+        NULL,\r
+        STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
+        gShellNetwork1HiiHandle, \r
+        L"Netmask",\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[0],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[1],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[2],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[3]\r
+        );\r
+\r
+      ShellPrintHiiEx(\r
+        -1, \r
+        -1, \r
+        NULL,\r
+        STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
+        gShellNetwork1HiiHandle, \r
+        L"Gateway",\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[0],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[1],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[2],\r
+        (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[3]\r
+        );\r
+    }\r
+\r
+    //\r
+    // Print dns server addresses list of the interface if has.\r
+    //\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_HEAD), gShellNetwork1HiiHandle);\r
+\r
+    for (Index = 0; Index < IfCb->DnsCnt; Index++) {\r
+      ShellPrintHiiEx(\r
+        -1, \r
+        -1, \r
+        NULL,\r
+        STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_BODY), \r
+        gShellNetwork1HiiHandle,\r
+        (UINTN) IfCb->DnsAddr[Index].Addr[0],\r
+        (UINTN) IfCb->DnsAddr[Index].Addr[1],\r
+        (UINTN) IfCb->DnsAddr[Index].Addr[2],\r
+        (UINTN) IfCb->DnsAddr[Index].Addr[3]\r
+        );\r
+\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);\r
+    }\r
   }\r
+  \r
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);\r
 \r
-  ArpResolved = TRUE;\r
-  return ;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Check whether the address to be configured conflicts with other hosts.\r
+  The clean process of the ifconfig command to clear interface info.\r
+\r
+  @param[in]   IfList    The pointer of IfList(interface list).\r
 \r
-  @param[in] NicInfo    The pointer to the NIC_INFO of the Nic to be configured.\r
-  @param[in] IpAddr     The IPv4 address to be configured to the Nic.\r
+  @retval EFI_SUCCESS    The ifconfig command clean processed successfully.\r
+  @retval others         The ifconfig command clean process failed.\r
 \r
-  @return TRUE      Some other host already uses the IpAddr.\r
-  @return FALSE     The address is unused.\r
 **/\r
-BOOLEAN\r
-EFIAPI\r
-IfconfigIsIpDuplicate (\r
-  IN  NIC_INFO                  *NicInfo,\r
-  IN  IP4_ADDR                  IpAddr\r
+EFI_STATUS\r
+IfConfigClearInterfaceInfo (\r
+  IN LIST_ENTRY    *IfList\r
   )\r
 {\r
-  EFI_ARP_PROTOCOL              *Arp;\r
-  EFI_ARP_CONFIG_DATA           ArpCfgData;\r
-  EFI_HANDLE                    ArpHandle;\r
-  ARP_REQUEST                   Request;\r
-  EFI_STATUS                    Status;\r
-\r
-  Arp           = NULL;\r
-  ArpHandle     = NULL;\r
-  ZeroMem (&Request, sizeof (ARP_REQUEST));\r
-\r
-  Status = NetLibCreateServiceChild (\r
-             NicInfo->Handle,\r
-             gImageHandle, \r
-             &gEfiArpServiceBindingProtocolGuid,\r
-             &ArpHandle\r
-             );\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return FALSE;\r
-  }\r
+  EFI_STATUS                Status;\r
+  LIST_ENTRY                *Entry;\r
+  LIST_ENTRY                *Next;\r
+  IFCONFIG_INTERFACE_CB     *IfCb;\r
+  EFI_IP4_CONFIG2_POLICY    Policy;\r
 \r
-  Status = gBS->OpenProtocol (\r
-                 ArpHandle,\r
-                 &gEfiArpProtocolGuid,\r
-                 (VOID**)&Arp,\r
-                 gImageHandle,\r
-                 ArpHandle,\r
-                 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                 );\r
+  Policy = Ip4Config2PolicyDhcp;\r
+  Status = EFI_SUCCESS;\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
+  if (IsListEmpty (IfList)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);\r
   }\r
 \r
   //\r
-  // Set up the Arp requests\r
+  // Go through the interface list.\r
   //\r
-  EFI_IP4_TO_U32 (Request.DestIp.v4)  = IpAddr;\r
-  EFI_IP4_TO_U32 (Request.LocalIp.v4) = 0xffffffff;\r
-  Request.LocalMac                    = NicInfo->NicAddress.MacAddr;\r
-  Request.MacLen                      = NicInfo->NicAddress.Len;\r
-  \r
-  Status = gBS->CreateEvent (\r
-                 EVT_NOTIFY_SIGNAL,\r
-                 TPL_CALLBACK,\r
-                 IfconfigOnArpResolved,\r
-                 (VOID *) &Request,\r
-                 &Request.OnResolved\r
-                 );\r
-  \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-  \r
-  ArpCfgData.SwAddressType    = 0x0800;\r
-  ArpCfgData.SwAddressLength  = 4;\r
-  ArpCfgData.StationAddress   = &Request.LocalIp;\r
-  ArpCfgData.EntryTimeOut     = 0;\r
-  ArpCfgData.RetryCount       = 3;\r
-  ArpCfgData.RetryTimeOut     = 0;\r
-  \r
-  Status = Arp->Configure (Arp, &ArpCfgData);\r
-  \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  Status = Arp->Request (\r
-                  Arp,\r
-                  &Request.DestIp,\r
-                  Request.OnResolved,\r
-                  &Request.DestMac\r
-                  );\r
-  \r
-  if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
-    goto ON_EXIT;\r
-  }\r
-\r
-  while (!ArpResolved) {\r
+  NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {\r
+    IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);\r
     \r
-  }\r
+    Status = IfCb->IfCfg->SetData (\r
+                            IfCb->IfCfg,\r
+                            Ip4Config2DataTypePolicy,\r
+                            sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                            &Policy\r
+                            );\r
 \r
-ON_EXIT:\r
-  if (Request.OnResolved != NULL) {\r
-    gBS->CloseEvent (Request.OnResolved);\r
+    if (EFI_ERROR (Status)) {\r
+      break;\r
+    }\r
   }\r
 \r
-  NetLibDestroyServiceChild (\r
-    NicInfo->Handle, \r
-    gImageHandle, \r
-    &gEfiArpServiceBindingProtocolGuid, \r
-    ArpHandle\r
-    );\r
-\r
-  return Request.Duplicate;\r
+  return Status;\r
 }\r
 \r
 /**\r
-  The callback function for the timer event used to get map.\r
+  The set process of the ifconfig command.\r
 \r
-  @param[in] Event    The event this function is registered to.\r
-  @param[in] Context  The context registered to the event.\r
-**/\r
-VOID\r
-EFIAPI\r
-TimeoutToGetMap (\r
-  IN EFI_EVENT      Event,\r
-  IN VOID           *Context\r
-  )\r
-{\r
-  mTimeout = TRUE;\r
-  return ;\r
-}\r
+  @param[in]   IfList    The pointer of IfList(interface list).\r
+  @param[in]   VarArg    The pointer of ARG_LIST(Args with "-s" option).\r
 \r
-/**\r
-  Create an IP child, use it to start the auto configuration, then destroy it.\r
-\r
-  @param[in] NicInfo    The pointer to the NIC_INFO of the Nic to be configured.\r
+  @retval EFI_SUCCESS    The ifconfig command set processed successfully.\r
+  @retval others         The ifconfig command set process failed.\r
 \r
-  @retval EFI_SUCCESS         The configuration is done.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
-IfconfigStartIp4(\r
-  IN NIC_INFO                   *NicInfo\r
+IfConfigSetInterfaceInfo (\r
+  IN LIST_ENTRY    *IfList,\r
+  IN ARG_LIST      *VarArg\r
   )\r
 {\r
-  EFI_IP4_PROTOCOL              *Ip4;\r
-  EFI_HANDLE                    Ip4Handle;\r
-  EFI_HANDLE                    TimerToGetMap;\r
-  EFI_IP4_CONFIG_DATA           Ip4ConfigData;\r
-  EFI_IP4_MODE_DATA             Ip4Mode;\r
-  EFI_STATUS                    Status;\r
 \r
-  //\r
-  // Get the Ip4ServiceBinding Protocol\r
-  //\r
-  Ip4Handle     = NULL;\r
-  Ip4           = NULL;\r
-  TimerToGetMap = NULL;\r
-\r
-  ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_START_SET_ADDR), gShellNetwork1HiiHandle);\r
+  EFI_STATUS                       Status;\r
+  IFCONFIG_INTERFACE_CB            *IfCb;\r
+  VAR_CHECK_CODE                   CheckCode;\r
+  EFI_EVENT                        TimeOutEvt;\r
+  EFI_EVENT                        MappedEvt;\r
+  BOOLEAN                          IsAddressOk;\r
 \r
-  Status = NetLibCreateServiceChild (\r
-             NicInfo->Handle,\r
-             gImageHandle,\r
-             &gEfiIp4ServiceBindingProtocolGuid,\r
-             &Ip4Handle\r
-             );\r
+  EFI_IP4_CONFIG2_POLICY           Policy;\r
+  EFI_IP4_CONFIG2_MANUAL_ADDRESS   ManualAddress;\r
+  UINTN                            DataSize;\r
+  EFI_IPv4_ADDRESS                 Gateway;\r
+  EFI_IPv4_ADDRESS                 *Dns;\r
+  ARG_LIST                         *Tmp;\r
+  UINTN                            Index;\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
+  CONST CHAR16* TempString;\r
 \r
-  Status = gBS->OpenProtocol (\r
-                 Ip4Handle,\r
-                 &gEfiIp4ProtocolGuid,\r
-                 (VOID **) &Ip4,\r
-                 NicInfo->Handle,\r
-                 gImageHandle,\r
-                 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                 );\r
+  Dns = NULL;\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
+  if (IsListEmpty (IfList)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);\r
+    return EFI_INVALID_PARAMETER;\r
   }\r
-\r
-  Ip4ConfigData.DefaultProtocol          = EFI_IP_PROTO_ICMP;\r
-  Ip4ConfigData.AcceptAnyProtocol        = FALSE;\r
-  Ip4ConfigData.AcceptIcmpErrors         = FALSE;\r
-  Ip4ConfigData.AcceptBroadcast          = FALSE;\r
-  Ip4ConfigData.AcceptPromiscuous        = FALSE;\r
-  Ip4ConfigData.UseDefaultAddress        = TRUE;\r
-  ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
-  ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
-  Ip4ConfigData.TypeOfService            = 0;\r
-  Ip4ConfigData.TimeToLive               = 1;\r
-  Ip4ConfigData.DoNotFragment            = FALSE;\r
-  Ip4ConfigData.RawData                  = FALSE;\r
-  Ip4ConfigData.ReceiveTimeout           = 0;\r
-  Ip4ConfigData.TransmitTimeout          = 0;\r
-\r
-  Status = Ip4->Configure (Ip4, &Ip4ConfigData);\r
-\r
-  if (Status == EFI_NO_MAPPING) {\r
-    mTimeout = FALSE;\r
-    Status  = gBS->CreateEvent (\r
-                    EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
-                    TPL_CALLBACK,\r
-                    TimeoutToGetMap,\r
-                    NULL,\r
-                    &TimerToGetMap\r
-                    );\r
-    \r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_EXIT;\r
-    }\r
-    \r
-    Status = gBS->SetTimer (\r
-                   TimerToGetMap,\r
-                   TimerRelative,\r
-                   MultU64x32 (SecondsToNanoSeconds, 5)\r
-                   );\r
-    \r
-    if (EFI_ERROR (Status)) {\r
-      goto ON_EXIT;\r
-    }\r
-\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_WAIT_SET_DONE), gShellNetwork1HiiHandle);\r
-    \r
-    while (!mTimeout) {\r
-      Ip4->Poll (Ip4);\r
   \r
-      if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && \r
-          Ip4Mode.IsConfigured) {       \r
-        break;\r
-      }\r
-    }    \r
-  }\r
-\r
-  Status = Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);\r
+  //\r
+  // Make sure to set only one interface each time.\r
+  //\r
+  IfCb   = NET_LIST_USER_STRUCT (IfList->ForwardLink, IFCONFIG_INTERFACE_CB, Link);\r
+  Status = EFI_SUCCESS;\r
 \r
-  if ((Status == EFI_SUCCESS) && Ip4Mode.IsConfigured) {\r
-    ShellPrintHiiEx(\r
-      -1, \r
-      -1, \r
-      NULL,\r
-      STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-      gShellNetwork1HiiHandle, \r
-      L"Default",\r
-      (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[0],\r
-      (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[1],\r
-      (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[2],\r
-      (UINTN)Ip4Mode.ConfigData.StationAddress.Addr[3]\r
-      );\r
-  }\r
-  \r
-ON_EXIT: \r
+  //\r
+  // Initialize check list mechanism.\r
+  //\r
+  CheckCode = IfConfigRetriveCheckListByName(\r
+                NULL,\r
+                NULL,\r
+                TRUE\r
+                );\r
 \r
+  //\r
+  // Create events & timers for asynchronous settings.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER,\r
+                  TPL_CALLBACK,\r
+                  NULL,\r
+                  NULL,\r
+                  &TimeOutEvt\r
+                  );\r
   if (EFI_ERROR (Status)) {\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_DEF_ADDR_FAIL), gShellNetwork1HiiHandle);\r
+    goto ON_EXIT;\r
   }\r
 \r
-  if (TimerToGetMap != NULL) {\r
-    gBS->SetTimer (TimerToGetMap, TimerCancel, 0);\r
-    gBS->CloseEvent (TimerToGetMap);\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_NOTIFY,\r
+                  IfConfigManualAddressNotify,\r
+                  &IsAddressOk,\r
+                  &MappedEvt\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
   }\r
 \r
-  NetLibDestroyServiceChild (\r
-    NicInfo->Handle,\r
-    gImageHandle,\r
-    &gEfiIp4ServiceBindingProtocolGuid,\r
-    Ip4Handle\r
-    );\r
-  \r
-  return Status;\r
-}\r
-\r
-/**\r
-  Set the address for the nic specified by the params.\r
+  //\r
+  // Parse the setting variables.\r
+  //\r
+  while (VarArg != NULL) {\r
+    //\r
+    // Check invalid parameters (duplication & unknown & conflict).\r
+    //\r
+    CheckCode = IfConfigRetriveCheckListByName(\r
+                  mSetCheckList,\r
+                  VarArg->Arg,\r
+                  FALSE\r
+                  );\r
 \r
-  @param[in] Argc       The count of the passed in Params.\r
-  @param[in] Params     The command line arguments for the set operation.\r
+    if (VarCheckOk != CheckCode) {\r
+      switch (CheckCode) {\r
+        case VarCheckDuplicate:\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_DUPLICATE_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);\r
+          break;\r
 \r
-  @retval EFI_SUCCESS   The address set operation is done.\r
-  @return               Some error occurs.\r
-**/\r
-SHELL_STATUS\r
-EFIAPI\r
-IfconfigSetNicAddr (\r
-  IN UINTN                      Argc,\r
-  IN CONST CHAR16               *Params\r
-  )\r
-{\r
-  NIC_IP4_CONFIG_INFO           *Config;\r
-  NIC_IP4_CONFIG_INFO           *OldConfig;\r
-  EFI_IP_ADDRESS                Ip;\r
-  EFI_IP_ADDRESS                Mask;\r
-  EFI_IP_ADDRESS                Gateway;\r
-  NIC_INFO                      *Info;\r
-  BOOLEAN                       Permanent;\r
-  SHELL_STATUS                  ShellStatus;\r
-  CONST CHAR16                  *Walker;\r
-  CHAR16                        *Temp;\r
-  CONST CHAR16                  *DhcpTemp;\r
-  CONST CHAR16                  *StaticTemp;\r
-  CONST CHAR16                  *PermTemp;\r
-  UINT32                        NetworkBytes1;\r
-  UINT32                        NetworkBytes2;\r
-  EFI_STATUS                    Status;\r
-\r
-  Walker  = Params;\r
-  Temp    = NULL;\r
-  Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
-  Info    = IfconfigFindNicByName (Temp);\r
-\r
-  if (Info == NULL) {\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_NOT_FOUND), gShellNetwork1HiiHandle, Temp);\r
-    return SHELL_NOT_FOUND;\r
-  }\r
+        case VarCheckConflict:\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_CONFLICT_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);\r
+          break;\r
 \r
-  Walker  += StrLen(Temp) + 1;\r
-  FreePool(Temp);\r
-  Temp = NULL;\r
-  Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")==NULL?0:StrStr(Walker, L" ")-Walker);\r
+        case VarCheckUnknown:\r
+          //\r
+          // To handle unsupported option.\r
+          //\r
+          TempString = PermanentString;\r
+          if (StringNoCaseCompare(&VarArg->Arg, &TempString) == 0) {\r
+            ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle, PermanentString);\r
+            goto ON_EXIT;\r
+          }\r
 \r
-  Config = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + 2 * sizeof (EFI_IP4_ROUTE_TABLE));\r
-  if (Config == NULL) {\r
-    return SHELL_OUT_OF_RESOURCES;\r
-  }\r
+          //\r
+          // To handle unknown option.\r
+          //\r
+          ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNKNOWN_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);\r
+          break;\r
 \r
-  Config->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Config + 1);\r
+        default:\r
+          break;\r
+      }\r
 \r
-  OldConfig = Info->ConfigInfo;\r
-  Permanent   = FALSE;\r
-  ShellStatus = SHELL_INVALID_PARAMETER;\r
+      VarArg = VarArg->Next;\r
+      continue;   \r
+    }\r
 \r
-  DhcpTemp = DhcpString;\r
-  StaticTemp = StaticString;\r
-  \r
-  if (StringNoCaseCompare(&Temp, &DhcpTemp) == 0) {\r
     //\r
-    // Validate the parameter for DHCP, two valid forms: eth0 DHCP and eth0 DHCP permanent\r
+    // Process valid variables.\r
     //\r
-    if ((Argc != 2) && (Argc!= 3)) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", Temp);  \r
-      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-      goto ON_EXIT;\r
-    }\r
+    if (StrCmp(VarArg->Arg, L"dhcp") == 0) {\r
+      //\r
+      // Set dhcp config policy\r
+      //\r
+      Policy = Ip4Config2PolicyDhcp;\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip4Config2DataTypePolicy,\r
+                              sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                              &Policy\r
+                              );\r
+\r
+      if (EFI_ERROR(Status)) {\r
+        goto ON_EXIT;\r
+      }\r
 \r
-    if (Argc == 3) {\r
-      Walker  += StrLen(Temp) + 1;\r
-      FreePool(Temp);\r
-      Temp    = NULL;\r
-      Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
+      VarArg= VarArg->Next;    \r
 \r
-      PermTemp = PermanentString;\r
-      if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
-        ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, L"ifconfig", Temp, PermanentString, L"Nothing");  \r
-        ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
+    } else if (StrCmp (VarArg->Arg, L"static") == 0) {\r
+      //\r
+      // Set manual config policy.\r
+      //\r
+      Policy = Ip4Config2PolicyStatic;\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip4Config2DataTypePolicy,\r
+                              sizeof (EFI_IP4_CONFIG2_POLICY),\r
+                              &Policy\r
+                              );\r
+\r
+      if (EFI_ERROR(Status)) {\r
         goto ON_EXIT;\r
       }\r
 \r
-      Permanent = TRUE;\r
-    }\r
+      VarArg= VarArg->Next;   \r
 \r
-    if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) &&\r
-        (OldConfig->Permanent == Permanent)) {\r
+      ZeroMem (&ManualAddress, sizeof (ManualAddress));\r
+    \r
+      //\r
+      // Get manual IP address.\r
+      //\r
+      Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.Address);\r
+      if (EFI_ERROR(Status)) {\r
+        goto ON_EXIT;\r
+      }\r
 \r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INTERFACE_CONFIGURED), gShellNetwork1HiiHandle, Info->Name);\r
-      ShellStatus = SHELL_ALREADY_STARTED;\r
-      goto ON_EXIT;\r
-    }\r
+      //\r
+      // Get subnetmask.\r
+      //    \r
+      VarArg = VarArg->Next;\r
+      Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.SubnetMask);\r
+      if (EFI_ERROR(Status)) {\r
+        goto ON_EXIT;\r
+      }\r
 \r
-    Config->Source = IP4_CONFIG_SOURCE_DHCP;\r
-  } else if (StringNoCaseCompare(&Temp, &StaticTemp) == 0) {\r
-    //\r
-    // validate the parameter, two forms: eth0 static IP NETMASK GATEWAY and\r
-    // eth0 static IP NETMASK GATEWAY permanent \r
-    //\r
-    if ((Argc != 5) && (Argc != 6)) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", Temp);  \r
-      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-      goto ON_EXIT;\r
-    }\r
+      //\r
+      // Get gateway.\r
+      //\r
+      VarArg = VarArg->Next;\r
+      Status = NetLibStrToIp4 (VarArg->Arg, &Gateway);\r
+      if (EFI_ERROR(Status)) {\r
+        goto ON_EXIT;\r
+      }\r
+      \r
+      IsAddressOk = FALSE;\r
+\r
+      Status = IfCb->IfCfg->RegisterDataNotify (\r
+                              IfCb->IfCfg,\r
+                              Ip4Config2DataTypeManualAddress,\r
+                              MappedEvt\r
+                              );\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_EXIT;\r
+      }\r
 \r
-    Walker  += StrLen(Temp) + 1;\r
-    FreePool(Temp);\r
-    Temp    = NULL;\r
-    Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
+      DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);\r
 \r
-    if (EFI_ERROR (NetLibStrToIp4 (Temp, &Ip.v4))) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
-      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-      goto ON_EXIT;\r
-    }\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip4Config2DataTypeManualAddress,\r
+                              DataSize,\r
+                              &ManualAddress\r
+                              );\r
 \r
-    Walker  += StrLen(Temp) + 1;\r
-    FreePool(Temp);\r
-    Temp    = NULL;\r
-    Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
-    if (EFI_ERROR (NetLibStrToIp4 (Temp, &Mask.v4))) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
-      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-      goto ON_EXIT;\r
-    }\r
+      if (Status == EFI_NOT_READY) {\r
+        gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000);\r
 \r
-    Walker  += StrLen(Temp) + 1;\r
-    FreePool(Temp);\r
-    Temp    = NULL;\r
-    if (Argc == 6) {\r
-      Temp    = StrnCatGrow(&Temp, NULL, Walker, StrStr(Walker, L" ")-Walker);\r
-    } else {\r
-      Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
-    }\r
-    if (EFI_ERROR (NetLibStrToIp4 (Temp, &Gateway.v4))) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), gShellNetwork1HiiHandle, Temp);\r
-      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-      goto ON_EXIT;\r
-    }\r
+        while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {\r
+          if (IsAddressOk) {\r
+            Status = EFI_SUCCESS;\r
+            break;\r
+          }\r
+        }\r
+      }\r
 \r
-    if (Argc == 6) {\r
-      Walker  += StrLen(Temp) + 1;\r
-      FreePool(Temp);\r
-      Temp    = NULL;\r
-      Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
+      IfCb->IfCfg->UnregisterDataNotify (\r
+                     IfCb->IfCfg,\r
+                     Ip4Config2DataTypeManualAddress,\r
+                     MappedEvt\r
+                     );\r
 \r
-      PermTemp = PermanentString;\r
-      if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
-        ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, L"ifconfig", Temp, PermanentString, L"Nothing");  \r
-        ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
+      if (EFI_ERROR (Status)) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);\r
         goto ON_EXIT;\r
       }\r
 \r
-      Permanent = TRUE;\r
-    }\r
+      //\r
+      // Set gateway.\r
+      //\r
+      DataSize = sizeof (EFI_IPv4_ADDRESS);\r
+\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip4Config2DataTypeGateway,\r
+                              DataSize,\r
+                              &Gateway\r
+                              );\r
+      VarArg = VarArg->Next;\r
+      \r
+    } else if (StrCmp (VarArg->Arg, L"dns") == 0) {\r
+      //\r
+      // Get DNS addresses.\r
+      //\r
+      VarArg = VarArg->Next;\r
+      Tmp    = VarArg;\r
+      Index  = 0;\r
+      while (Tmp != NULL) {\r
+        Index ++;\r
+        Tmp = Tmp->Next;\r
+      }\r
 \r
-    NetworkBytes1 = NTOHL (Ip.Addr[0]);\r
-    NetworkBytes2 = NTOHL (Mask.Addr[0]);\r
-    if ((Ip.Addr[0] == 0) || (Mask.Addr[0] == 0) ||\r
-        !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {\r
+      Dns   = AllocatePool (Index * sizeof (EFI_IPv4_ADDRESS));\r
+      ASSERT(Dns != NULL);\r
+      Tmp   = VarArg;\r
+      Index = 0;\r
+      while (Tmp != NULL) {\r
+        Status = NetLibStrToIp4 (Tmp->Arg, Dns + Index);\r
+        if (EFI_ERROR(Status)) {\r
+          goto ON_EXIT;\r
+        }\r
+        Index ++;\r
+        Tmp = Tmp->Next;\r
+      }\r
+      \r
+      VarArg = Tmp;\r
 \r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_ADDR_PAIR), gShellNetwork1HiiHandle);\r
-      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-      goto ON_EXIT;\r
+      //\r
+      // Set DNS addresses.\r
+      //\r
+      DataSize = Index * sizeof (EFI_IPv4_ADDRESS);\r
+\r
+      Status = IfCb->IfCfg->SetData (\r
+                              IfCb->IfCfg,\r
+                              Ip4Config2DataTypeDnsServer,\r
+                              DataSize,\r
+                              Dns\r
+                              );\r
     }\r
+  }\r
 \r
-    NetworkBytes1 = NTOHL (Gateway.Addr[0]);\r
-    if (!IP4_NET_EQUAL (Ip.Addr[0], Gateway.Addr[0], Mask.Addr[0]) ||\r
-        !NetIp4IsUnicast (NetworkBytes1, NetworkBytes2)) {\r
-        \r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), gShellNetwork1HiiHandle);\r
-      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-      goto ON_EXIT;\r
-    }\r
+ON_EXIT:\r
+  if (Dns != NULL) {\r
+    FreePool (Dns);\r
+  }\r
+  \r
+  return EFI_SUCCESS;\r
 \r
-    //\r
-    // Set the configuration up, two route table entries are added:\r
-    // one for the direct connected network, and another for the \r
-    // default gateway. Remember, some structure members are cleared\r
-    // by AllocateZeroPool\r
-    //\r
-    Config->Source = IP4_CONFIG_SOURCE_STATIC;\r
-    Config->Ip4Info.RouteTableSize = 2;\r
+}\r
 \r
-    CopyMem (&Config->Ip4Info.StationAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
-    CopyMem (&Config->Ip4Info.SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));\r
+/**\r
+  The ifconfig command main process.\r
 \r
-    Ip.Addr[0] = Ip.Addr[0] & Mask.Addr[0];\r
+  @param[in]   Private    The pointer of IFCONFIG_PRIVATE_DATA.\r
 \r
-    CopyMem (&Config->Ip4Info.RouteTable[0].SubnetAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
-    CopyMem (&Config->Ip4Info.RouteTable[0].SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));\r
-    CopyMem (&Config->Ip4Info.RouteTable[1].GatewayAddress, &Gateway.v4, sizeof (EFI_IPv4_ADDRESS));\r
-  } else {\r
-    // neither static or DHCP.  error.\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ifconfig");  \r
-    ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
-    goto ON_EXIT;\r
-  }\r
+  @retval EFI_SUCCESS    ifconfig command processed successfully.\r
+  @retval others         The ifconfig command process failed.\r
 \r
-  CopyMem (&Config->NicAddr, &Info->NicAddress, sizeof (NIC_ADDR));\r
-  Config->Permanent = Permanent;\r
+**/\r
+EFI_STATUS\r
+IfConfig (\r
+  IN IFCONFIG_PRIVATE_DATA    *Private\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
 \r
   //\r
-  // Use HII service to set NIC address\r
+  // Get configure information of all interfaces.\r
   //\r
-  ShellStatus = IfconfigSetNicAddrByHii (Info, Config);\r
-  if (ShellStatus != SHELL_SUCCESS) {\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_SET_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);\r
-    goto ON_EXIT;\r
-  } \r
+  Status = IfConfigGetInterfaceInfo (\r
+             Private->IfName,\r
+             &Private->IfList\r
+             );\r
 \r
-  Status = IfconfigStartIp4 (Info);\r
-  if (EFI_ERROR(Status)) {\r
-    ShellStatus = SHELL_ACCESS_DENIED;\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
   }\r
 \r
-  if (ShellStatus != SHELL_SUCCESS) {\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_IP_CHILD_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);\r
+  switch (Private->OpCode) {\r
+  case IfConfigOpList:\r
+    Status = IfConfigShowInterfaceInfo (&Private->IfList);\r
+    break;\r
+\r
+  case IfConfigOpClear:\r
+    Status = IfConfigClearInterfaceInfo (&Private->IfList);\r
+    break;\r
+\r
+  case IfConfigOpSet:\r
+    Status = IfConfigSetInterfaceInfo (&Private->IfList, Private->VarArg);\r
+    break;\r
+\r
+  default:\r
+    Status = EFI_ABORTED;\r
   }\r
-  \r
+\r
 ON_EXIT:\r
-  SHELL_FREE_NON_NULL(Config);\r
-  \r
-  return ShellStatus;\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
-  Show the address information for the nic specified.\r
+  The ifconfig command cleanup process, free the allocated memory.\r
+\r
+  @param[in]   Private    The pointer of  IFCONFIG_PRIVATE_DATA.\r
 \r
-  @param[in] Name   A pointer to the string containg the nic's name, if NULL, \r
-                    all nics' information is shown.\r
 **/\r
 VOID\r
-EFIAPI\r
-IfconfigShowNicInfo (\r
-  IN CONST CHAR16           *Name\r
+IfConfigCleanup (\r
+  IN IFCONFIG_PRIVATE_DATA  *Private\r
   )\r
 {\r
   LIST_ENTRY                *Entry;\r
   LIST_ENTRY                *NextEntry;\r
-  NIC_INFO                  *NicInfo;\r
-  UINT32                    Index;\r
-  EFI_IP4_IPCONFIG_DATA     *Ip4Config;\r
-  EFI_IPv4_ADDRESS          Gateway;\r
-  CONST CHAR16              *TempString;\r
+  IFCONFIG_INTERFACE_CB     *IfCb;\r
+  ARG_LIST                  *ArgNode;\r
+  ARG_LIST                  *ArgHead;\r
 \r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
-    NicInfo = BASE_CR (Entry, NIC_INFO, Link);\r
+  ASSERT (Private != NULL);\r
 \r
-    TempString = (CHAR16*)NicInfo->Name;\r
-    if ((Name != NULL) && (StringNoCaseCompare (&Name, &TempString) != 0)) {\r
-      continue;\r
-    }\r
-\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NAME), gShellNetwork1HiiHandle, NicInfo->Name);\r
-\r
-    ShellPrintHiiEx(\r
-    -1,\r
-    -1,\r
-    NULL,\r
-    STRING_TOKEN(STR_IFCONFIG_SHOW_MAC_ADDR), \r
-    gShellNetwork1HiiHandle, \r
-    (UINTN)NicInfo->NicAddress.MacAddr.Addr[0], \r
-    (UINTN)NicInfo->NicAddress.MacAddr.Addr[1], \r
-    (UINTN)NicInfo->NicAddress.MacAddr.Addr[2],\r
-    (UINTN)NicInfo->NicAddress.MacAddr.Addr[3], \r
-    (UINTN)NicInfo->NicAddress.MacAddr.Addr[4], \r
-    (UINTN)NicInfo->NicAddress.MacAddr.Addr[5]\r
-    );    \r
-\r
-    Print (L"  Media State: %s\n", NicInfo->MediaPresent ? L"Media present" : L"Media disconnected");\r
-\r
-    if (NicInfo->ConfigInfo == NULL) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_NIC_NOT_CONFIGURED), gShellNetwork1HiiHandle);\r
-      continue;\r
-    } \r
+  //\r
+  // Clean the list which save the set config Args.\r
+  //\r
+  if (Private->VarArg != NULL) {\r
+    ArgHead = Private->VarArg;\r
 \r
-    if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_DHCP) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"DHCP");\r
-    } else if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"STATIC");\r
-    } else {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), gShellNetwork1HiiHandle, L"Unknown");\r
+    while (ArgHead->Next != NULL) {\r
+      ArgNode = ArgHead->Next;\r
+      FreePool (ArgHead);\r
+      ArgHead = ArgNode;\r
     }\r
 \r
-    ShellPrintHiiEx(-1, -1, NULL,\r
-      STRING_TOKEN (STR_IFCONFIG_PERMANENT_STATUS),\r
-      gShellNetwork1HiiHandle,\r
-      (NicInfo->ConfigInfo->Permanent? L"TRUE":L"FALSE")\r
-      );\r
-\r
-    Ip4Config = &NicInfo->ConfigInfo->Ip4Info;\r
-\r
-    ShellPrintHiiEx(\r
-      -1, \r
-      -1, \r
-      NULL,\r
-      STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-      gShellNetwork1HiiHandle, \r
-      L"IP address",\r
-      (UINTN)Ip4Config->StationAddress.Addr[0],\r
-      (UINTN)Ip4Config->StationAddress.Addr[1],\r
-      (UINTN)Ip4Config->StationAddress.Addr[2],\r
-      (UINTN)Ip4Config->StationAddress.Addr[3]\r
-      );\r
-    ShellPrintHiiEx(\r
-      -1, \r
-      -1, \r
-      NULL,\r
-      STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-      gShellNetwork1HiiHandle, \r
-      L"Mask",\r
-      (UINTN)Ip4Config->SubnetMask.Addr[0],\r
-      (UINTN)Ip4Config->SubnetMask.Addr[1],\r
-      (UINTN)Ip4Config->SubnetMask.Addr[2],\r
-      (UINTN)Ip4Config->SubnetMask.Addr[3]\r
-      );\r
-\r
-    ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));\r
-    \r
-    for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {\r
-      if ((CompareMem (&Ip4Config->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&\r
-          (CompareMem (&Ip4Config->RouteTable[Index].SubnetMask   , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){\r
-        CopyMem (&Gateway, &Ip4Config->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
-      }\r
-    }\r
-   \r
-    ShellPrintHiiEx(\r
-      -1, \r
-      -1, \r
-      NULL,\r
-      STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-      gShellNetwork1HiiHandle, \r
-      L"Gateway",\r
-      (UINTN)Gateway.Addr[0],\r
-      (UINTN)Gateway.Addr[1],\r
-      (UINTN)Gateway.Addr[2],\r
-      (UINTN)Gateway.Addr[3]\r
-      );\r
-\r
-    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, Ip4Config->RouteTableSize);\r
-\r
-    for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);\r
-\r
-      ShellPrintHiiEx(\r
-        -1, \r
-        -1, \r
-        NULL,\r
-        STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-        gShellNetwork1HiiHandle, \r
-        L"Subnet",\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[0],\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[1],\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[2],\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetAddress.Addr[3]\r
-        );\r
-\r
-      ShellPrintHiiEx(\r
-        -1, \r
-        -1, \r
-        NULL,\r
-        STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-        gShellNetwork1HiiHandle, \r
-        L"Netmask",\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[0],\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[1],\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[2],\r
-        (UINTN)Ip4Config->RouteTable[Index].SubnetMask.Addr[3]\r
-        );\r
-\r
-      ShellPrintHiiEx(\r
-        -1, \r
-        -1, \r
-        NULL,\r
-        STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR), \r
-        gShellNetwork1HiiHandle, \r
-        L"Gateway",\r
-        (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[0],\r
-        (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[1],\r
-        (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[2],\r
-        (UINTN)Ip4Config->RouteTable[Index].GatewayAddress.Addr[3]\r
-        );\r
-    }\r
+    FreePool (ArgHead);\r
   }\r
 \r
-  return ;\r
-}\r
+  if (Private->IfName != NULL) {\r
+    FreePool (Private->IfName);\r
+  }\r
 \r
-/**\r
-  Clear address configuration for the nic specified.\r
+  //\r
+  // Clean the IFCONFIG_INTERFACE_CB list.\r
+  //\r
+  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->IfList) {\r
+    IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);\r
 \r
-  @param[in] Name     A pointer to the string containg the nic's name, \r
-                      if NULL, all nics address configurations are cleared.\r
+    RemoveEntryList (&IfCb->Link);\r
 \r
-  @retval EFI_SUCCESS The address configuration is cleared.\r
-  @return             Some error occurs.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-IfconfigClearNicAddr (\r
-  IN CONST CHAR16                     *Name\r
-  )\r
-{\r
-  LIST_ENTRY                    *Entry;\r
-  LIST_ENTRY                    *NextEntry;\r
-  NIC_INFO                      *Info;\r
-  EFI_STATUS                    Status;\r
-  \r
-  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
-    Info = BASE_CR (Entry, NIC_INFO, Link);\r
+    if (IfCb->IfInfo != NULL) {\r
 \r
-    if ((Name != NULL) && (StrCmp (Name, Info->Name) != 0)) {\r
-      continue;\r
+      FreePool (IfCb->IfInfo);\r
     }\r
 \r
-//    if (Info->NicIp4Config == NULL) { \r
-      Status = IfconfigSetNicAddrByHii (Info, NULL);\r
-//    } else {\r
-//      Status = Info->NicIp4Config->SetInfo (Info->NicIp4Config, NULL, TRUE);\r
-//    }\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return Status;\r
-    }\r
+    FreePool (IfCb);\r
   }\r
 \r
-  return EFI_SUCCESS;\r
-  \r
+  FreePool (Private);\r
 }\r
 \r
 /**\r
@@ -1644,6 +1157,10 @@ IfconfigClearNicAddr (
 \r
   @param[in] ImageHandle  Handle to the Image (NULL if Internal).\r
   @param[in] SystemTable  Pointer to the System Table (NULL if Internal).\r
+\r
+  @retval EFI_SUCCESS    ifconfig command processed successfully.\r
+  @retval others         The ifconfig command process failed.\r
+  \r
 **/\r
 SHELL_STATUS\r
 EFIAPI\r
@@ -1652,131 +1169,125 @@ ShellCommandRunIfconfig (
   IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
-  EFI_STATUS          Status;\r
-  LIST_ENTRY          *Package;\r
-  CHAR16              *ProblemParam;\r
-  SHELL_STATUS        ShellStatus;\r
-  BOOLEAN             ListOperation;\r
-  BOOLEAN             ClearOperation;\r
-  BOOLEAN             SetOperation;\r
-  CONST CHAR16        *Item;\r
-  LIST_ENTRY          *Entry;\r
-  NIC_INFO            *Info;\r
-\r
-  InitializeListHead (&NicInfoList);\r
-  Status = EFI_INVALID_PARAMETER;\r
-  ShellStatus = SHELL_SUCCESS;\r
+  EFI_STATUS                Status;\r
+  IFCONFIG_PRIVATE_DATA     *Private;\r
+  LIST_ENTRY                *ParamPackage;\r
+  CONST CHAR16              *ValueStr;\r
+  ARG_LIST                  *ArgList;\r
+  CHAR16                    *ProblemParam;\r
+  CHAR16                    *Str;\r
+\r
+  Private = NULL;\r
+\r
+  Status = ShellCommandLineParseEx (mIfConfigCheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);\r
+  if (EFI_ERROR (Status)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);\r
+    goto ON_EXIT;\r
+  }\r
 \r
   //\r
-  // initialize the shell lib (we must be in non-auto-init...)\r
+  // To handle unsupported option.\r
   //\r
-  Status = ShellInitialize();\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle,L"-c");\r
+    goto ON_EXIT;\r
+  }\r
 \r
   //\r
-  // parse the command line\r
+  // To handle no option.\r
   //\r
-  Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);\r
-  if (EFI_ERROR(Status)) {\r
-    if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);  \r
-      FreePool(ProblemParam);\r
-      ShellStatus = SHELL_INVALID_PARAMETER;\r
-    } else {\r
-      ASSERT(FALSE);\r
-    }\r
-\r
-    goto Done;\r
+  if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&\r
+      !ShellCommandLineGetFlag (ParamPackage, L"-l")) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_OPTION), gShellNetwork1HiiHandle);\r
+    goto ON_EXIT;\r
   }\r
 \r
-  ClearOperation = ShellCommandLineGetFlag(Package, L"-c");\r
-  ListOperation  = ShellCommandLineGetFlag(Package, L"-l");\r
-  SetOperation   = ShellCommandLineGetFlag(Package, L"-s");\r
-\r
-  if ((ClearOperation && ListOperation)\r
-    ||(SetOperation   && ListOperation)\r
-    ||(ClearOperation && SetOperation)\r
-    ) {\r
-    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");  \r
-    ShellStatus = SHELL_INVALID_PARAMETER;\r
-    goto Done;\r
-  } else if (!ClearOperation && !ListOperation && !SetOperation) {\r
-    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ifconfig");  \r
-    ShellStatus = SHELL_INVALID_PARAMETER;\r
-    goto Done;\r
+  //\r
+  // To handle conflict options.\r
+  //\r
+  if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||\r
+      ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||\r
+      ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");\r
+    goto ON_EXIT;\r
   }\r
-    \r
-    \r
-  Status = IfconfigGetAllNicInfoByHii ();\r
-  if (EFI_ERROR (Status)) {\r
-    if (mIp4ConfigExist) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_NIC_FAIL), gShellNetwork1HiiHandle, Status);\r
-    } else {\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellNetwork1HiiHandle, L"ifconfig", L"gEfiIp4ConfigProtocolGuid", &gEfiIp4ConfigProtocolGuid);  \r
-    }\r
 \r
-    return SHELL_NOT_FOUND;\r
+  Status = EFI_INVALID_PARAMETER;\r
+\r
+  Private = AllocateZeroPool (sizeof (IFCONFIG_PRIVATE_DATA));\r
+\r
+  if (Private == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
   }\r
 \r
-  if (ListOperation) {\r
-    Item = ShellCommandLineGetValue (Package, L"-l");\r
+  InitializeListHead (&Private->IfList);\r
 \r
-    if (Item != NULL && CountSubItems(Item) > 1) {\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"ifconfig", Item, L"-l");  \r
-      ShellStatus = SHELL_INVALID_PARAMETER;\r
-      goto Done;\r
-    } \r
+  //\r
+  // To get interface name for the list option.\r
+  //\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {\r
+    Private->OpCode = IfConfigOpList;\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");\r
+    if (ValueStr != NULL) {\r
+      Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);\r
+      ASSERT (Str != NULL);\r
+      Private->IfName = Str;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // To get interface name for the clear option.\r
+  //\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {\r
+    Private->OpCode = IfConfigOpClear;\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");\r
+    if (ValueStr != NULL) {\r
+      Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);\r
+      ASSERT (Str != NULL);\r
+      Private->IfName = Str;\r
+    }\r
+  }\r
+  \r
+  //\r
+  // To get interface name and corresponding Args for the set option.\r
+  //\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {\r
+    ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");\r
+    if (ValueStr == NULL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_INTERFACE), gShellNetwork1HiiHandle);\r
+      goto ON_EXIT;\r
+    }\r
     \r
     //\r
-    // Show the configuration.\r
+    // To split the configuration into multi-section.\r
     //\r
-    IfconfigShowNicInfo (Item);\r
-  } else if (SetOperation) {\r
-    Item = ShellCommandLineGetValue (Package, L"-s");\r
+    ArgList         = SplitStrToList (ValueStr, L' ');\r
+    ASSERT (ArgList != NULL);\r
 \r
-    //\r
-    // The correct command line arguments for setting address are:\r
-    // IfConfig -s eth0 DHCP [permanent]\r
-    // IfConfig -s eth0 static ip netmask gateway [permanent]\r
-    //\r
-    if (Item == NULL || (CountSubItems(Item) < 2) || (CountSubItems(Item) > 6) || (CountSubItems(Item) == 4)) {\r
-      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_NO_VALUE), gShellNetwork1HiiHandle, L"ifconfig", L"-s");  \r
-      ShellStatus = SHELL_INVALID_PARAMETER;\r
-      goto Done;\r
-    }\r
+    Private->OpCode = IfConfigOpSet;\r
+    Private->IfName = ArgList->Arg;\r
 \r
-    ShellStatus = IfconfigSetNicAddr (CountSubItems(Item), Item);\r
-  } else if (ClearOperation) {\r
-    Item = ShellCommandLineGetValue (Package, L"-c");\r
+    Private->VarArg = ArgList->Next;\r
 \r
-    if (Item != NULL && CountSubItems(Item) > 1) {\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"ifconfig", Item, L"-c");  \r
-      ShellStatus = SHELL_INVALID_PARAMETER;\r
-      goto Done;\r
+    if (Private->IfName == NULL || Private->VarArg == NULL) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);\r
+      goto ON_EXIT;\r
     }\r
-\r
-    IfconfigClearNicAddr (Item);\r
-  } else {\r
-    ASSERT(FALSE);\r
   }\r
+  \r
+  //\r
+  // Main process of ifconfig.\r
+  //\r
+  Status = IfConfig (Private);\r
 \r
-Done:\r
-  while (!IsListEmpty (&NicInfoList)) {\r
-    Entry = NicInfoList.ForwardLink;\r
-    Info  = BASE_CR (Entry, NIC_INFO, Link);\r
-\r
-    RemoveEntryList (Entry);\r
-\r
-    if (Info->ConfigInfo != NULL) {\r
-      FreePool (Info->ConfigInfo);\r
-    }\r
-\r
-    FreePool (Info);\r
-  }\r
+ON_EXIT:\r
 \r
-  if (Package != NULL) {\r
-    ShellCommandLineFreeVarList(Package);\r
+  ShellCommandLineFreeVarList (ParamPackage);\r
+  \r
+  if (Private != NULL) {\r
+    IfConfigCleanup (Private);\r
   }\r
 \r
-  return (ShellStatus);\r
+  return Status;\r
 }\r