Add Network1 profile.
authorjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 25 Mar 2011 20:47:02 +0000 (20:47 +0000)
committerjcarsey <jcarsey@6f19259b-4bc3-4df7-8a09-765794883524>
Fri, 25 Mar 2011 20:47:02 +0000 (20:47 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11423 6f19259b-4bc3-4df7-8a09-765794883524

ShellPkg/Library/UefiShellNetwork1CommandsLib/Ia32/Tsc.c [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/Ipf/Itc.c [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni [new file with mode: 0644]
ShellPkg/Library/UefiShellNetwork1CommandsLib/X64/Tsc.c [new file with mode: 0644]

diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ia32/Tsc.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ia32/Tsc.c
new file mode 100644 (file)
index 0000000..e2eae99
--- /dev/null
@@ -0,0 +1,28 @@
+/** @file\r
+  The implement to read TSC in IA32 platform.\r
+\r
+  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+\r
+/**\r
+  Reads and returns the current value of the Time Stamp Counter (TSC).\r
+\r
+  @return The current value of TSC.\r
+\r
+**/\r
+UINT64\r
+ReadTime ()\r
+{\r
+  return AsmReadTsc ();\r
+}\r
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
new file mode 100644 (file)
index 0000000..2e8a09f
--- /dev/null
@@ -0,0 +1,1746 @@
+/** @file\r
+  The implementation for ifcommand shell command.\r
+\r
+  Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+**/\r
+\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
+\r
+STATIC CONST UINTN SEC_TO_NS            = 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
+\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
+\r
+/**\r
+  Find the NIC_INFO by the specified nic name.\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
+  )\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
+\r
+    if (StringNoCaseCompare (&Name, &TempString) == 0) {\r
+      return Info;\r
+    }\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
+  //\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
+\r
+  //\r
+  // Inspect if ChildHandle is one of the agents.\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[in] 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
+\r
+  //\r
+  // Locate all EFI Hii Config Access protocols\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
+    }\r
+  }\r
+\r
+  FreePool (Handles);\r
+  return Status;  \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]      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                    Offset,\r
+  IN UINTN                    Width,\r
+  IN CONST UINT8              *Block\r
+  )\r
+\r
+{\r
+  CHAR16                      *OriString;\r
+\r
+  OriString = String;\r
+\r
+  StrCpy (String, L"&OFFSET=");\r
+  String += StrLen (L"&OFFSET=");\r
+  String += UnicodeSPrint (String, 20, L"%x", Offset);\r
+\r
+  StrCpy (String,L"&WIDTH=");\r
+  String += StrLen (L"&WIDTH=");\r
+  String += UnicodeSPrint (String, 20, L"%x", Width);\r
+\r
+  if (Block != NULL) {\r
+    StrCpy (String,L"&VALUE=");\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
+\r
+/**\r
+  Converts the unicode character of the string from uppercase to lowercase.\r
+  This is a internal function.\r
+\r
+  @param ConfigString  String to be converted\r
+**/\r
+CHAR16* \r
+EFIAPI\r
+HiiToLower (\r
+  IN CHAR16   *ConfigString\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
+  }\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
+  EFI_DEVICE_PATH_PROTOCOL   *DevicePath;\r
+  CHAR16                     *String;\r
+  UINTN                      Index;\r
+  UINT8                      *Buffer;\r
+  UINTN                      DevicePathLength;\r
+  UINTN                      NameLength;\r
+\r
+  //\r
+  // Get the device path from handle installed EFI HII Config Access protocol\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                 DriverHandle,\r
+                 &gEfiDevicePathProtocolGuid,\r
+                 (VOID **) &DevicePath\r
+                 );\r
+  if (EFI_ERROR (Status)) {\r
+    return NULL;\r
+  }\r
+\r
+  DevicePathLength = GetDevicePathSize (DevicePath);\r
+  NameLength = StrLen (Name);\r
+  ConfigHdr = AllocateZeroPool ((5 + sizeof (EFI_GUID) * 2 + 6 + NameLength * 4 + 6 + DevicePathLength * 2 + 1) * sizeof (CHAR16));\r
+  if (ConfigHdr == NULL) {\r
+    return NULL;\r
+  } \r
+\r
+  String = ConfigHdr;\r
+  StrCpy (String, L"GUID=");\r
+  String += StrLen (L"GUID=");\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
+\r
+  //\r
+  // Append L"&NAME="\r
+  //\r
+  StrCpy (String, L"&NAME=");\r
+  String += StrLen (L"&NAME=");\r
+  for (Index = 0; Index < NameLength ; Index++) {\r
+    String += UnicodeSPrint (String, 10, L"00%x", Name[Index]);\r
+  }\r
+  \r
+  //\r
+  // Append L"&PATH="\r
+  //\r
+  StrCpy (String, L"&PATH=");\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
+\r
+  return (HiiToLower(ConfigHdr));\r
+}\r
+\r
+/**\r
+  Get network physical device NIC information.\r
+\r
+  @param[in] Handle         The network physical device handle.\r
+  @param[out] NicAddr       NIC information.\r
+\r
+  @retval EFI_SUCCESS         Get NIC information successfully.\r
+**/                  \r
+EFI_STATUS\r
+EFIAPI\r
+IfConfigGetNicMacInfo (\r
+  IN  EFI_HANDLE                    Handle,\r
+  OUT NIC_ADDR                      *NicAddr\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
+}\r
+\r
+/**\r
+  Get network physical device NIC information.\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
+\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
+{\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
+  *MediaPresentSupported = SnpMode.MediaPresentSupported;\r
+  *MediaPresent = SnpMode.MediaPresent;\r
+\r
+ON_ERROR:\r
+\r
+  NetLibDestroyServiceChild (\r
+    Handle,\r
+    gImageHandle, \r
+    &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+    MnpHandle\r
+    );\r
+\r
+  return Status;\r
+\r
+}\r
+\r
+/**\r
+  Get all Nic's information through HII service.\r
+\r
+  @retval EFI_SUCCESS         All the nic information is collected.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IfconfigGetAllNicInfoByHii (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  EFI_HANDLE                    *Handles;\r
+  UINTN                         HandleCount;\r
+  CHAR16                        *ConfigResp;\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
+\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
+\r
+  //\r
+  // Locate all network device handles\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                 ByProtocol,\r
+                 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                 NULL,\r
+                 &HandleCount,\r
+                 &Handles\r
+                 );\r
+  if (EFI_ERROR (Status) || (HandleCount == 0)) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = GetChildHandle (Handles[Index], &ChildHandle);\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
+    }\r
+    //\r
+    // Construct configuration request string header\r
+    //\r
+    ConfigHdr = ConstructConfigHdr (&gEfiNicIp4ConfigVariableGuid, EFI_NIC_IP4_CONFIG_VARIABLE, ChildHandle);\r
+    Length = StrLen (ConfigHdr);\r
+    ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));\r
+    if (ConfigResp == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+    StrCpy (ConfigResp, ConfigHdr);\r
\r
+    //\r
+    // Append OFFSET/WIDTH pair\r
+    //\r
+    String = ConfigResp + Length;\r
+    Offset = 0;\r
+    AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL);\r
+\r
+    NicInfo = AllocateZeroPool (sizeof (NIC_INFO));\r
+    if (NicInfo == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+    NicInfo->Handle       = Handles[Index];\r
+\r
+    //\r
+    // Get network physical devcie MAC information\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
+    }\r
+\r
+    //\r
+    // Get media status\r
+    //\r
+    IfConfigGetNicMediaStatus (Handles[Index], &NicInfo->MediaPresentSupported, &NicInfo->MediaPresent);\r
+\r
+    NicConfigRequest = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
+    if (NicConfigRequest == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    //\r
+    // Get network parameters by HII service\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
+      }\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
+    //\r
+    InsertTailList (&NicInfoList, &NicInfo->Link);\r
+\r
+    FreePool (NicConfigRequest);\r
+    FreePool (ConfigResp);\r
+    FreePool (ConfigHdr);\r
+  }\r
+\r
+  FreePool (Handles);\r
+\r
+  return EFI_SUCCESS;\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
+\r
+  FreePool (Handles);\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Set the address for the specified nic by HII service.\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
+\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
+  )\r
+{\r
+  EFI_STATUS                    Status;\r
+  SHELL_STATUS                  ShellStatus;\r
+  NIC_IP4_CONFIG_INFO           *NicConfig;\r
+  CHAR16                        *ConfigResp;\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
+\r
+  Length = StrLen (ConfigHdr);\r
+  ConfigResp = AllocateZeroPool ((Length + NIC_ITEM_CONFIG_SIZE * 2 + 100) * sizeof (CHAR16));\r
+  StrCpy (ConfigResp, ConfigHdr);\r
+\r
+  NicConfig = AllocateZeroPool (NIC_ITEM_CONFIG_SIZE);\r
+  if (NicConfig == NULL) {\r
+    ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (Config != NULL) {\r
+    CopyMem (NicConfig, Config, sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE) * Config->Ip4Info.RouteTableSize);\r
+  }\r
+\r
+  //\r
+  // Append OFFSET/WIDTH pair\r
+  //\r
+  String = ConfigResp + Length;\r
+  Offset = 0;\r
+  AppendOffsetWidthValue (String, Offset, NIC_ITEM_CONFIG_SIZE, NULL);\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
+\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
+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
+  return ShellStatus;\r
+}\r
+\r
+/**\r
+  The callback function for the Arp address resolved event.\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
+  Request = (ARP_REQUEST *) Context;\r
+  ASSERT (Request != NULL);\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
+      );\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
+    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
+  }\r
+\r
+  ArpResolved = TRUE;\r
+  return ;\r
+}\r
+\r
+/**\r
+  Check whether the address to be configured conflicts with other hosts.\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
+\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
+  )\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
+\r
+  Status = gBS->OpenProtocol (\r
+                 ArpHandle,\r
+                 &gEfiArpProtocolGuid,\r
+                 (VOID**)&Arp,\r
+                 gImageHandle,\r
+                 ArpHandle,\r
+                 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                 );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Set up the Arp requests\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
+    \r
+  }\r
+\r
+ON_EXIT:\r
+  if (Request.OnResolved != NULL) {\r
+    gBS->CloseEvent (Request.OnResolved);\r
+  }\r
+\r
+  NetLibDestroyServiceChild (\r
+    NicInfo->Handle, \r
+    gImageHandle, \r
+    &gEfiArpServiceBindingProtocolGuid, \r
+    ArpHandle\r
+    );\r
+\r
+  return Request.Duplicate;\r
+}\r
+\r
+/**\r
+  The callback function for the timer event used to get map.\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
+\r
+/**\r
+  Create an IP child, use it to start the auto configuration, then destory it.\r
+\r
+  @param[in] NicInfo    The pointer to the NIC_INFO of the Nic to be configured.\r
+\r
+  @retval EFI_SUCCESS         The configuration is done.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IfconfigStartIp4(\r
+  IN NIC_INFO                   *NicInfo\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
+\r
+  Status = NetLibCreateServiceChild (\r
+             NicInfo->Handle,\r
+             gImageHandle,\r
+             &gEfiIp4ServiceBindingProtocolGuid,\r
+             &Ip4Handle\r
+             );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\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
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_EXIT;\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 - 1,\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 (SEC_TO_NS, 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
+  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
+  if (EFI_ERROR (Status)) {\r
+    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_GET_DEF_ADDR_FAIL), gShellNetwork1HiiHandle);\r
+  }\r
+\r
+  if (TimerToGetMap != NULL) {\r
+    gBS->SetTimer (TimerToGetMap, TimerCancel, 0);\r
+    gBS->CloseEvent (TimerToGetMap);\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
+  @param[in] Argc       The count of the passed in Params.\r
+  @param[in] Params     The command line arguments for the set operation.\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
+\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
+\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
+  Config->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Config + 1);\r
+\r
+  OldConfig = Info->ConfigInfo;\r
+  Permanent   = FALSE;\r
+  ShellStatus = SHELL_INVALID_PARAMETER;\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 perment\r
+    //\r
+    if ((Argc != 2) && (Argc!= 3)) {\r
+      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);\r
+      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\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
+\r
+      PermTemp = PermanentString;\r
+      if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
+        ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");\r
+        ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      Permanent = TRUE;\r
+    }\r
+\r
+    if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) &&\r
+        (OldConfig->Perment == Permanent)) {\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
+    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 perment\r
+    //\r
+    if ((Argc != 5) && (Argc != 6)) {\r
+      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, Temp);\r
+      ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\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
+\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
+\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
+\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
+\r
+    if (Argc == 6) {\r
+      Walker  += StrLen(Temp) + 1;\r
+      FreePool(Temp);\r
+      Temp    = NULL;\r
+      Temp    = StrnCatGrow(&Temp, NULL, Walker, 0);\r
+\r
+      PermTemp = PermanentString;\r
+      if (StringNoCaseCompare(&Temp, &PermTemp) != 0) {\r
+        ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_OP2), gShellNetwork1HiiHandle, Temp, PermanentString, L"Nothing");\r
+        ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      Permanent = TRUE;\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
+\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
+\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
+\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
+    CopyMem (&Config->Ip4Info.StationAddress, &Ip.v4, sizeof (EFI_IPv4_ADDRESS));\r
+    CopyMem (&Config->Ip4Info.SubnetMask, &Mask.v4, sizeof (EFI_IPv4_ADDRESS));\r
+\r
+    Ip.Addr[0] = Ip.Addr[0] & Mask.Addr[0];\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);\r
+    ASSERT(ShellStatus == SHELL_INVALID_PARAMETER);\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  CopyMem (&Config->NicAddr, &Info->NicAddress, sizeof (NIC_ADDR));\r
+  Config->Perment = Permanent;\r
+\r
+  //\r
+  // Use HII service to set NIC address\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
+\r
+  Status = IfconfigStartIp4 (Info);\r
+  if (EFI_ERROR(Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+  }\r
+\r
+  if (ShellStatus != SHELL_SUCCESS) {\r
+    ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_IP_CHILD_FAIL), gShellNetwork1HiiHandle, ShellStatus^MAX_BIT);\r
+  }\r
+  \r
+ON_EXIT:\r
+  SHELL_FREE_NON_NULL(Config);\r
+  \r
+  return ShellStatus;\r
+}\r
+\r
+/**\r
+  Show the address information for the nic specified.\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
+  )\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
+\r
+  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &NicInfoList) {\r
+    NicInfo = BASE_CR (Entry, NIC_INFO, Link);\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
+    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
+    }\r
+\r
+    ShellPrintHiiEx(-1, -1, NULL,\r
+      STRING_TOKEN (STR_IFCONFIG_PERMENT_STATUS),\r
+      gShellNetwork1HiiHandle,\r
+      (NicInfo->ConfigInfo->Perment? 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
+  }\r
+\r
+  return ;\r
+}\r
+\r
+/**\r
+  Clear address configuration for the nic specified.\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
+\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
+\r
+    if ((Name != NULL) && (StrCmp (Name, Info->Name) != 0)) {\r
+      continue;\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
+  }\r
+\r
+  return EFI_SUCCESS;\r
+  \r
+}\r
+\r
+/**\r
+  Function for 'ifconfig' command.\r
+\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
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunIfconfig (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  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
+\r
+  //\r
+  // initialize the shell lib (we must be in non-auto-init...)\r
+  //\r
+  Status = ShellInitialize();\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  //\r
+  // parse the command line\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, ProblemParam);\r
+      FreePool(ProblemParam);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+    } else {\r
+      ASSERT(FALSE);\r
+    }\r
+\r
+    goto Done;\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);\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);\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    goto Done;\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"gEfiIp4ConfigProtocolGuid", &gEfiIp4ConfigProtocolGuid);\r
+    }\r
+\r
+    return SHELL_NOT_FOUND;\r
+  }\r
+\r
+  if (ListOperation) {\r
+    Item = ShellCommandLineGetValue (Package, L"-l");\r
+\r
+    if (Item != NULL && CountSubItems(Item) > 1) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-l");\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto Done;\r
+    } \r
+    \r
+    //\r
+    // Show the configuration.\r
+    //\r
+    IfconfigShowNicInfo (Item);\r
+  } else if (SetOperation) {\r
+    Item = ShellCommandLineGetValue (Package, L"-s");\r
+\r
+    //\r
+    // The correct command line arguments for setting address are:\r
+    // IfConfig -s eth0 DHCP [perment]\r
+    // IfConfig -s eth0 static ip netmask gateway [perment]\r
+    //\r
+    if (Item == NULL || (CountSubItems(Item) < 2) || (CountSubItems(Item) > 6) || (CountSubItems(Item) == 4)) {\r
+      ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-s");\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+\r
+    ShellStatus = IfconfigSetNicAddr (CountSubItems(Item), Item);\r
+  } else if (ClearOperation) {\r
+    Item = ShellCommandLineGetValue (Package, L"-c");\r
+\r
+    if (Item != NULL && CountSubItems(Item) > 1) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellNetwork1HiiHandle, L"-c");\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+\r
+    IfconfigClearNicAddr (Item);\r
+  } else {\r
+    ASSERT(FALSE);\r
+  }\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
+\r
+  if (Package != NULL) {\r
+    ShellCommandLineFreeVarList(Package);\r
+  }\r
+\r
+  return (ShellStatus);\r
+}\r
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ipf/Itc.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ipf/Itc.c
new file mode 100644 (file)
index 0000000..131e5c0
--- /dev/null
@@ -0,0 +1,28 @@
+/** @file\r
+  The implement to read ITC in IA64 platform.\r
+\r
+  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+\r
+/**\r
+  Reads and returns the current value of the Interval Timer Counter Register (ITC).\r
+\r
+  @return The current value of ITC.\r
+\r
+**/\r
+UINT64\r
+ReadTime ()\r
+{\r
+  return AsmReadItc ();\r
+}\r
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
new file mode 100644 (file)
index 0000000..493de26
--- /dev/null
@@ -0,0 +1,1563 @@
+/** @file\r
+  The implementation for Ping shell command.\r
+\r
+  Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "UefiShellNetwork1CommandsLib.h"\r
+\r
+#define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))\r
+\r
+\r
+//\r
+// Function templates to match the IPv4 and IPv6 commands that we use.\r
+//\r
+typedef \r
+EFI_STATUS\r
+(EFIAPI *PING_IPX_POLL)(\r
+  IN VOID          *This\r
+  );  \r
+\r
+typedef \r
+EFI_STATUS\r
+(EFIAPI *PING_IPX_TRANSMIT)(\r
+  IN VOID          *This,\r
+  IN VOID          *Token\r
+  );\r
+\r
+typedef \r
+EFI_STATUS\r
+(EFIAPI *PING_IPX_RECEIVE)(\r
+  IN VOID          *This,\r
+  IN VOID          *Token\r
+  ); \r
+\r
+typedef\r
+EFI_STATUS\r
+(EFIAPI *PING_IPX_CANCEL)(\r
+  IN VOID          *This,\r
+  IN VOID          *Token OPTIONAL\r
+  );\r
+\r
+///\r
+/// A set of pointers to either IPv6 or IPv4 functions.  \r
+/// Unknown which one to the ping command.\r
+///\r
+typedef struct {\r
+  PING_IPX_TRANSMIT             Transmit;\r
+  PING_IPX_RECEIVE              Receive;\r
+  PING_IPX_CANCEL               Cancel;\r
+  PING_IPX_POLL                 Poll;\r
+}PING_IPX_PROTOCOL;\r
+\r
+\r
+typedef union {\r
+  VOID                  *RxData;\r
+  VOID                  *TxData;\r
+} PING_PACKET;\r
+\r
+//\r
+// PING_IPX_COMPLETION_TOKEN\r
+// structures are used for both transmit and receive operations. \r
+// This version is IP-unaware.\r
+//\r
+typedef struct {\r
+  EFI_EVENT               Event;\r
+  EFI_STATUS              Status;\r
+  PING_PACKET             Packet;\r
+} PING_IPX_COMPLETION_TOKEN;\r
+\r
+#pragma pack(1)\r
+typedef struct _ICMPX_ECHO_REQUEST_REPLY {\r
+  UINT8                       Type;\r
+  UINT8                       Code;\r
+  UINT16                      Checksum;\r
+  UINT16                      Identifier;\r
+  UINT16                      SequenceNum;\r
+  UINT64                      TimeStamp;\r
+  UINT8                       Data[1];\r
+} ICMPX_ECHO_REQUEST_REPLY;\r
+#pragma pack()\r
+\r
+typedef struct _PING_ICMP_TX_INFO {\r
+  LIST_ENTRY                Link;\r
+  UINT16                    SequenceNum;\r
+  UINT64                    TimeStamp;\r
+  PING_IPX_COMPLETION_TOKEN *Token;\r
+} PING_ICMPX_TX_INFO;\r
+\r
+#define DEFAULT_TIMEOUT       5000\r
+#define MAX_SEND_NUMBER       10000\r
+#define MAX_BUFFER_SIZE       32768\r
+#define DEFAULT_TIMER_PERIOD  358049\r
+#define ONE_SECOND            10000000\r
+#define PING_IP_CHOICE_IP4    1\r
+#define PING_IP_CHOICE_IP6    2\r
+#define DEFAULT_SEND_COUNT    10\r
+#define DEFAULT_BUFFER_SIZE   16\r
+#define ICMP_V4_ECHO_REQUEST  0x8\r
+#define ICMP_V4_ECHO_REPLY    0x0\r
+\r
+#define PING_PRIVATE_DATA_SIGNATURE  SIGNATURE_32 ('P', 'i', 'n', 'g')\r
+typedef struct _PING_PRIVATE_DATA {\r
+  UINT32                      Signature;\r
+  EFI_HANDLE                  NicHandle;\r
+  EFI_HANDLE                  IpChildHandle;\r
+  EFI_EVENT                   Timer;\r
+\r
+  EFI_STATUS                  Status;\r
+  LIST_ENTRY                  TxList;\r
+  UINT16                      RxCount;\r
+  UINT16                      TxCount;\r
+  UINT64                      RttSum;\r
+  UINT64                      RttMin;\r
+  UINT64                      RttMax;\r
+  UINT32                      SequenceNum;\r
+\r
+  UINT32                      SendNum;\r
+  UINT32                      BufferSize;\r
+  UINT32                      IpChoice;\r
+\r
+  PING_IPX_PROTOCOL           ProtocolPointers;\r
+  VOID                        *IpProtocol;\r
+  UINT8                       SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
+  UINT8                       DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS)        , sizeof(EFI_IPv4_ADDRESS)          )];\r
+  PING_IPX_COMPLETION_TOKEN   RxToken;\r
+} PING_PRIVATE_DATA;\r
+\r
+UINT16\r
+EFIAPI\r
+NetChecksum (\r
+  IN UINT8   *Buffer,\r
+  IN UINT32  Length\r
+  )\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Calculate the internet checksum (see RFC 1071)\r
+\r
+Arguments:\r
+\r
+  Packet             - Buffer which contains the data to be checksummed\r
+  Length             - Length to be checksummed\r
+\r
+Returns:\r
+\r
+  Checksum           - Returns the 16 bit ones complement of \r
+                       ones complement sum of 16 bit words\r
+\r
+--*/\r
+{\r
+  UINT32  Sum;\r
+  UINT8   Odd;\r
+  UINT16  *Packet;\r
+\r
+  Packet  = (UINT16 *) Buffer;\r
+\r
+  Sum     = 0;\r
+  Odd     = (UINT8) (Length & 1);\r
+  Length >>= 1;\r
+  while (Length--) {\r
+    Sum += *Packet++;\r
+  }\r
+\r
+  if (Odd) {\r
+    Sum += *(UINT8 *) Packet;\r
+  }\r
+\r
+  Sum = (Sum & 0xffff) + (Sum >> 16);\r
+\r
+  //\r
+  // in case above carried\r
+  //\r
+  Sum += Sum >> 16;\r
+\r
+  return (UINT16) Sum;\r
+}\r
+\r
+/**\r
+  Reads and returns the current value of register.\r
+  In IA64, the register is the Interval Timer Vector (ITV).\r
+  In X86(IA32/X64), the register is the Time Stamp Counter (TSC)\r
+\r
+  @return The current value of the register.\r
+\r
+**/\r
+UINT64\r
+EFIAPI\r
+ReadTime (\r
+  VOID\r
+  );\r
+\r
+STATIC CONST SHELL_PARAM_ITEM    PingParamList[] = {\r
+  {\r
+    L"-l",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-n",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-_s",\r
+    TypeValue\r
+  },\r
+  {\r
+    L"-_ip6",\r
+    TypeFlag\r
+  },\r
+  {\r
+    NULL,\r
+    TypeMax\r
+  },\r
+};\r
+\r
+//\r
+// Global Variables in Ping command.\r
+//\r
+STATIC CONST CHAR16      *mDstString;\r
+STATIC CONST CHAR16      *mSrcString;\r
+STATIC UINT64            mFrequency = 0;\r
+\r
+/**\r
+  Get and caculate the frequency in tick/ms.\r
+  The result is saved in the globle variable mFrequency\r
+\r
+  @retval EFI_SUCCESS    Caculated the frequency successfully.\r
+  @retval Others         Failed to caculate the frequency.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetFrequency (\r
+  VOID\r
+  )\r
+{\r
+  EFI_STATUS               Status;\r
+  EFI_CPU_ARCH_PROTOCOL    *Cpu;\r
+  UINT64                   CurrentTick;\r
+  UINT64                   TimerPeriod;\r
+\r
+  Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    TimerPeriod = DEFAULT_TIMER_PERIOD;\r
+  }\r
+\r
+  //\r
+  // The timer period is in femtosecond (1 femtosecond is 1e-15 second).\r
+  // So 1e+12 is divided by timer period to produce the freq in tick/ms.\r
+  //\r
+  mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Caculate a duration in ms.\r
+\r
+  @param[in]  Begin     The start point of time.\r
+  @param[in]  End       The end point of time.\r
+\r
+  @return               The duration in ms.\r
+  @retval 0             The parameters were not valid.\r
+**/\r
+UINT64\r
+EFIAPI\r
+CalculateTick (\r
+  IN UINT64    Begin,\r
+  IN UINT64    End\r
+  )\r
+{\r
+  if (End <= Begin) {\r
+    return (0);\r
+  }\r
+  return DivU64x64Remainder (End - Begin, mFrequency, NULL);\r
+}\r
+\r
+/**\r
+  Destroy PING_ICMPX_TX_INFO, and recollect the memory.\r
+\r
+  @param[in]    TxInfo    The pointer to PING_ICMPX_TX_INFO.\r
+  @param[in]    IpChoice  Whether the token is IPv4 or IPv6\r
+**/\r
+VOID\r
+EFIAPI\r
+PingDestroyTxInfo (\r
+  IN PING_ICMPX_TX_INFO    *TxInfo,\r
+  IN UINT32                IpChoice\r
+  )\r
+{\r
+  EFI_IP6_TRANSMIT_DATA    *Ip6TxData;\r
+  EFI_IP4_TRANSMIT_DATA    *Ip4TxData;\r
+  EFI_IP6_FRAGMENT_DATA    *FragData;\r
+  UINTN                    Index;\r
+\r
+  if (TxInfo == NULL) {\r
+    return;\r
+  }\r
+\r
+  if (TxInfo->Token != NULL) {\r
+\r
+    if (TxInfo->Token->Event != NULL) {\r
+      gBS->CloseEvent (TxInfo->Token->Event);\r
+    }\r
+\r
+    if (TxInfo->Token->Packet.TxData != NULL) {\r
+      if (IpChoice == PING_IP_CHOICE_IP6) {\r
+        Ip6TxData = TxInfo->Token->Packet.TxData;\r
+\r
+        if (Ip6TxData->OverrideData != NULL) {\r
+          FreePool (Ip6TxData->OverrideData);\r
+        }\r
+\r
+        if (Ip6TxData->ExtHdrs != NULL) {\r
+          FreePool (Ip6TxData->ExtHdrs);\r
+        }\r
+\r
+        for (Index = 0; Index < Ip6TxData->FragmentCount; Index++) {\r
+          FragData = Ip6TxData->FragmentTable[Index].FragmentBuffer;\r
+          if (FragData != NULL) {\r
+            FreePool (FragData);\r
+          }\r
+        }\r
+      } else {\r
+        Ip4TxData = TxInfo->Token->Packet.TxData;\r
+\r
+        if (Ip4TxData->OverrideData != NULL) {\r
+          FreePool (Ip4TxData->OverrideData);\r
+        }\r
+\r
+        for (Index = 0; Index < Ip4TxData->FragmentCount; Index++) {\r
+          FragData = Ip4TxData->FragmentTable[Index].FragmentBuffer;\r
+          if (FragData != NULL) {\r
+            FreePool (FragData);\r
+          }\r
+        }\r
+      }\r
+    }\r
+\r
+    FreePool (TxInfo->Token);\r
+  }\r
+\r
+  FreePool (TxInfo);\r
+}\r
+\r
+/**\r
+  Match the request, and reply with SequenceNum/TimeStamp.\r
+\r
+  @param[in]    Private    The pointer to PING_PRIVATE_DATA.\r
+  @param[in]    Packet     The pointer to ICMPX_ECHO_REQUEST_REPLY.\r
+\r
+  @retval EFI_SUCCESS      The match is successful.\r
+  @retval EFI_NOT_FOUND    The reply can't be matched with any request.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ping6MatchEchoReply (\r
+  IN PING_PRIVATE_DATA           *Private,\r
+  IN ICMPX_ECHO_REQUEST_REPLY    *Packet\r
+  )\r
+{\r
+  PING_ICMPX_TX_INFO     *TxInfo;\r
+  LIST_ENTRY             *Entry;\r
+  LIST_ENTRY             *NextEntry;\r
+\r
+  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
+    TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);\r
+\r
+    if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) {\r
+      Private->RxCount++;\r
+      RemoveEntryList (&TxInfo->Link);\r
+      PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
+      return EFI_SUCCESS;\r
+    }\r
+  }\r
+\r
+  return EFI_NOT_FOUND;\r
+}\r
+\r
+/**\r
+  The original intention is to send a request.\r
+  Currently, the application retransmits an icmp6 echo request packet\r
+  per second in sendnumber times that is specified by the user.\r
+  Because nothing can be done here, all things move to the timer rountine.\r
+\r
+  @param[in]    Event      A EFI_EVENT type event.\r
+  @param[in]    Context    The pointer to Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ping6OnEchoRequestSent (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+}\r
+\r
+/**\r
+  receive reply, match and print reply infomation.\r
+\r
+  @param[in]    Event      A EFI_EVENT type event.\r
+  @param[in]    Context    The pointer to context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ping6OnEchoReplyReceived (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  PING_PRIVATE_DATA           *Private;\r
+  ICMPX_ECHO_REQUEST_REPLY    *Reply;\r
+  UINT32                      PayLoad;\r
+  UINT64                      Rtt;\r
+  CHAR8                       Near;\r
+\r
+  Private = (PING_PRIVATE_DATA *) Context;\r
+\r
+  if (Private == NULL || Private->Status == EFI_ABORTED || Private->Signature != PING_PRIVATE_DATA_SIGNATURE) {\r
+    return;\r
+  }\r
+\r
+  if (Private->RxToken.Packet.RxData == NULL) {\r
+    return;\r
+  }\r
+\r
+  if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+    Reply   = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer;\r
+    PayLoad = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength;\r
+    if (((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->NextHeader != IP6_ICMP) {\r
+      goto ON_EXIT;\r
+    }\r
+    if (!IP6_IS_MULTICAST ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && \r
+        !EFI_IP6_EQUAL (&((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv6_ADDRESS*)&Private->DstAddress)) {\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) {\r
+      goto ON_EXIT;\r
+    }\r
+  } else {\r
+    Reply   = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer;\r
+    PayLoad = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength;\r
+    if (!IP4_IS_MULTICAST (EFI_IP4(*(EFI_IPv4_ADDRESS*)Private->DstAddress)) && \r
+        !EFI_IP4_EQUAL (&((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv4_ADDRESS*)&Private->DstAddress)) {\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    if ((Reply->Type != ICMP_V4_ECHO_REPLY) || (Reply->Code != 0)) {\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+  \r
+\r
+  if (PayLoad != Private->BufferSize) {\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Check whether the reply matches the sent request before.\r
+  //\r
+  Status = Ping6MatchEchoReply (Private, Reply);\r
+  if (EFI_ERROR(Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Display statistics on this icmp6 echo reply packet.\r
+  //\r
+  Rtt  = CalculateTick (Reply->TimeStamp, ReadTime ());\r
+  if (Rtt != 0) {\r
+    Near = (CHAR8) '=';\r
+  } else {\r
+    Near = (CHAR8) '<';\r
+  }\r
+\r
+  Private->RttSum += Rtt;\r
+  Private->RttMin  = Private->RttMin > Rtt ? Rtt : Private->RttMin;\r
+  Private->RttMax  = Private->RttMax < Rtt ? Rtt : Private->RttMax;\r
+\r
+  ShellPrintHiiEx (\r
+    -1,\r
+    -1,\r
+    NULL,\r
+    STRING_TOKEN (STR_PING_REPLY_INFO),\r
+    gShellNetwork1HiiHandle,\r
+    PayLoad,\r
+    mDstString,\r
+    Reply->SequenceNum,\r
+    Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->HopLimit:0,\r
+    Near,\r
+    Rtt\r
+    );\r
+\r
+ON_EXIT:\r
+\r
+  if (Private->RxCount < Private->SendNum) {\r
+    //\r
+    // Continue to receive icmp echo reply packets.\r
+    //\r
+    Private->RxToken.Status = EFI_ABORTED;\r
+\r
+    Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      Private->Status = EFI_ABORTED;\r
+    }\r
+  } else {\r
+    //\r
+    // All reply have already been received from the dest host.\r
+    //\r
+    Private->Status = EFI_SUCCESS;\r
+  }\r
+  //\r
+  // Singal to recycle the each rxdata here, not at the end of process.\r
+  //\r
+  gBS->SignalEvent (Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal:((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal);\r
+}\r
+\r
+/**\r
+  Create a PING_IPX_COMPLETION_TOKEN.\r
+\r
+  @param[in]    Private        The pointer of PING_PRIVATE_DATA.\r
+  @param[in]    TimeStamp      The TimeStamp of request.\r
+  @param[in]    SequenceNum    The SequenceNum of request.\r
+\r
+  @return The pointer of PING_IPX_COMPLETION_TOKEN.\r
+\r
+**/\r
+PING_IPX_COMPLETION_TOKEN *\r
+EFIAPI\r
+PingGenerateToken (\r
+  IN PING_PRIVATE_DATA    *Private,\r
+  IN UINT64                TimeStamp,\r
+  IN UINT16                SequenceNum\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  PING_IPX_COMPLETION_TOKEN   *Token;\r
+  VOID                        *TxData;\r
+  ICMPX_ECHO_REQUEST_REPLY    *Request;\r
+  UINT16                        HeadSum;\r
+  UINT16                        TempChecksum;\r
+\r
+  Request = AllocateZeroPool (Private->BufferSize);\r
+  if (Request == NULL) {\r
+    return NULL;\r
+  }\r
+  TxData = AllocateZeroPool (Private->IpChoice==PING_IP_CHOICE_IP6?sizeof (EFI_IP6_TRANSMIT_DATA):sizeof (EFI_IP4_TRANSMIT_DATA));\r
+  if (TxData == NULL) {\r
+    FreePool (Request);\r
+    return NULL;\r
+  }\r
+  Token = AllocateZeroPool (sizeof (PING_IPX_COMPLETION_TOKEN));\r
+  if (Token == NULL) {\r
+    FreePool (Request);\r
+    FreePool (TxData);\r
+    return NULL;\r
+  }\r
+\r
+  //\r
+  // Assembly echo request packet.\r
+  //\r
+  Request->Type        = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);\r
+  Request->Code        = 0;\r
+  Request->SequenceNum = SequenceNum;\r
+  Request->Identifier  = 0;\r
+  Request->Checksum    = 0;\r
+\r
+  //\r
+  // Assembly token for transmit.\r
+  //\r
+  if (Private->IpChoice==PING_IP_CHOICE_IP6) {\r
+    ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength                   = 0;\r
+    ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs                         = NULL;\r
+    ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData                    = 0;\r
+    ((EFI_IP6_TRANSMIT_DATA*)TxData)->DataLength                      = Private->BufferSize;\r
+    ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentCount                   = 1;\r
+    ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request;\r
+    ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize;\r
+  } else {\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsLength                   = 0;\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsBuffer                   = NULL;\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->OverrideData                    = 0;\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->TotalDataLength                 = Private->BufferSize;\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentCount                   = 1;\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request;\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize;\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[0]      = Private->DstAddress[0];\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[1]      = Private->DstAddress[1];\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[2]      = Private->DstAddress[2];\r
+    ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[3]      = Private->DstAddress[3];\r
+\r
+    HeadSum = NetChecksum ((UINT8 *) Request, Private->BufferSize);\r
+    Request->TimeStamp   = TimeStamp;\r
+    TempChecksum = NetChecksum ((UINT8 *) &Request->TimeStamp, sizeof (UINT64));\r
+    Request->Checksum = (UINT16)(~NetAddChecksum (HeadSum, TempChecksum));\r
+  }\r
+\r
+\r
+  Token->Status         = EFI_ABORTED;\r
+  Token->Packet.TxData  = TxData;\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  Ping6OnEchoRequestSent,\r
+                  Private,\r
+                  &Token->Event\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Request);\r
+    FreePool (TxData);\r
+    FreePool (Token);\r
+    return NULL;\r
+  }\r
+\r
+  return Token;\r
+}\r
+\r
+/**\r
+  Transmit the PING_IPX_COMPLETION_TOKEN.\r
+\r
+  @param[in]    Private    The pointer of PING_PRIVATE_DATA.\r
+\r
+  @retval EFI_SUCCESS             Transmitted successfully.\r
+  @retval EFI_OUT_OF_RESOURCES    No memory is available on the platform.\r
+  @retval others                  Transmitted unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PingSendEchoRequest (\r
+  IN PING_PRIVATE_DATA    *Private\r
+  )\r
+{\r
+  EFI_STATUS             Status;\r
+  PING_ICMPX_TX_INFO     *TxInfo;\r
+\r
+  TxInfo = AllocateZeroPool (sizeof (PING_ICMPX_TX_INFO));\r
+\r
+  if (TxInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  TxInfo->TimeStamp   = ReadTime ();\r
+  TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);\r
+  TxInfo->Token       = PingGenerateToken (\r
+                          Private,\r
+                          TxInfo->TimeStamp,\r
+                          TxInfo->SequenceNum\r
+                          );\r
+\r
+  if (TxInfo->Token == NULL) {\r
+    PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  ASSERT(Private->ProtocolPointers.Transmit != NULL);\r
+  Status = Private->ProtocolPointers.Transmit (Private->IpProtocol, TxInfo->Token);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
+    return Status;\r
+  }\r
+\r
+  InsertTailList (&Private->TxList, &TxInfo->Link);\r
+  Private->TxCount++;\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Place a completion token into the receive packet queue to receive the echo reply.\r
+\r
+  @param[in]    Private    The pointer of PING_PRIVATE_DATA.\r
+\r
+  @retval EFI_SUCCESS      Put the token into the receive packet queue successfully.\r
+  @retval others           Put the token into the receive packet queue unsuccessfully.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+Ping6ReceiveEchoReply (\r
+  IN PING_PRIVATE_DATA    *Private\r
+  )\r
+{\r
+  EFI_STATUS    Status;\r
+\r
+  ZeroMem (&Private->RxToken, sizeof (PING_IPX_COMPLETION_TOKEN));\r
+\r
+  Status = gBS->CreateEvent (\r
+                  EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  Ping6OnEchoReplyReceived,\r
+                  Private,\r
+                  &Private->RxToken.Event\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  Private->RxToken.Status = EFI_NOT_READY;\r
+\r
+  return (Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken));\r
+}\r
+\r
+/**\r
+  Remove the timeout request from the list.\r
+\r
+  @param[in]    Event    A EFI_EVENT type event.\r
+  @param[in]    Context  The pointer to Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ping6OnTimerRoutine (\r
+  IN EFI_EVENT    Event,\r
+  IN VOID         *Context\r
+  )\r
+{\r
+  EFI_STATUS             Status;\r
+  PING_PRIVATE_DATA      *Private;\r
+  PING_ICMPX_TX_INFO     *TxInfo;\r
+  LIST_ENTRY             *Entry;\r
+  LIST_ENTRY             *NextEntry;\r
+  UINT64                 Time;\r
+\r
+  Private = (PING_PRIVATE_DATA *) Context;\r
+  if (Private->Signature != PING_PRIVATE_DATA_SIGNATURE) {\r
+    Private->Status = EFI_NOT_FOUND;\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Retransmit icmp6 echo request packets per second in sendnumber times.\r
+  //\r
+  if (Private->TxCount < Private->SendNum) {\r
+\r
+    Status = PingSendEchoRequest (Private);\r
+    if (Private->TxCount != 0){\r
+      if (EFI_ERROR (Status)) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_SEND_REQUEST), gShellNetwork1HiiHandle, Private->TxCount + 1);\r
+      }\r
+    }\r
+  }\r
+  //\r
+  // Check whether any icmp6 echo request in the list timeout.\r
+  //\r
+  NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
+    TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);\r
+    Time   = CalculateTick (TxInfo->TimeStamp, ReadTime ());\r
+\r
+    //\r
+    // Remove the timeout echo request from txlist.\r
+    //\r
+    if (Time > DEFAULT_TIMEOUT) {\r
+\r
+      if (EFI_ERROR (TxInfo->Token->Status)) {\r
+        Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token);\r
+      }\r
+      //\r
+      // Remove the timeout icmp6 echo request from list.\r
+      //\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_TIMEOUT), gShellNetwork1HiiHandle, TxInfo->SequenceNum);\r
+\r
+      RemoveEntryList (&TxInfo->Link);\r
+      PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
+\r
+      //\r
+      // We dont need to wait for this some other time...\r
+      //\r
+      Private->RxCount++;\r
+\r
+      if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {\r
+        //\r
+        // All the left icmp6 echo request in the list timeout.\r
+        //\r
+        Private->Status = EFI_TIMEOUT;\r
+      }\r
+    }\r
+  }\r
+}\r
+\r
+/**\r
+  Determine if a IP4 address is Link Local.\r
+\r
+  169.254.1.0 through 169.254.254.255 is link local.\r
+\r
+  @param[in] Address  The address to test.\r
+\r
+  @retval TRUE      It is.\r
+  @retval FALSE     It is not.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+PingNetIp4IsLinkLocalAddr (\r
+  IN CONST EFI_IPv4_ADDRESS *Address\r
+  )\r
+{\r
+  return ((BOOLEAN)(Address->Addr[0] == 169 && Address->Addr[1] == 254 && Address->Addr[2] >= 1 && Address->Addr[2] <= 254));\r
+}\r
+\r
+/**\r
+  Determine if a IP4 address is unspecified.\r
+\r
+  @param[in] Address  The address to test.\r
+\r
+  @retval TRUE      It is.\r
+  @retval FALSE     It is not.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+PingNetIp4IsUnspecifiedAddr (\r
+  IN CONST EFI_IPv4_ADDRESS *Address\r
+  )\r
+{\r
+  return  ((BOOLEAN)((ReadUnaligned32 ((UINT32*)&Address->Addr[0])) == 0x00000000));\r
+}\r
+\r
+/**\r
+  Create a valid IP instance.\r
+\r
+  @param[in]    Private    The pointer of PING_PRIVATE_DATA.\r
+\r
+  @retval EFI_SUCCESS              Create a valid IPx instance successfully.\r
+  @retval EFI_ABORTED              Locate handle with ipx service binding protocol unsuccessfully.\r
+  @retval EFI_INVALID_PARAMETER    The source address is unspecified when the destination address is a link-local address.\r
+  @retval EFI_OUT_OF_RESOURCES     No memory is available on the platform.\r
+  @retval EFI_NOT_FOUND            The source address is not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+PingCreateIpInstance (\r
+  IN  PING_PRIVATE_DATA    *Private\r
+  )\r
+{\r
+  EFI_STATUS                       Status;\r
+  UINTN                            HandleIndex;\r
+  UINTN                            HandleNum;\r
+  EFI_HANDLE                       *HandleBuffer;\r
+  EFI_SERVICE_BINDING_PROTOCOL     *EfiSb;\r
+  VOID                             *IpXCfg;\r
+  EFI_IP6_CONFIG_DATA              Ip6Config;\r
+  EFI_IP4_CONFIG_DATA              Ip4Config;\r
+  VOID                             *IpXInterfaceInfo;\r
+  UINTN                            IfInfoSize;\r
+  EFI_IPv6_ADDRESS                 *Addr;\r
+  UINTN                            AddrIndex;\r
+\r
+  HandleBuffer      = NULL;\r
+  EfiSb             = NULL;\r
+  IpXInterfaceInfo  = NULL;\r
+  IfInfoSize        = 0;\r
+\r
+  //\r
+  // Locate all the handles with ip6 service binding protocol.\r
+  //\r
+  Status = gBS->LocateHandleBuffer (\r
+                  ByProtocol,\r
+                  Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,\r
+                  NULL,\r
+                  &HandleNum,\r
+                  &HandleBuffer\r
+                  );\r
+  if (EFI_ERROR (Status) || (HandleNum == 0)) {\r
+    return EFI_ABORTED;\r
+  }\r
+  //\r
+  // Source address is required when pinging a link-local address on multi-\r
+  // interfaces host.\r
+  //\r
+  if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+    if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) &&\r
+        NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) &&\r
+        (HandleNum > 1)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_ERROR;\r
+    }\r
+  } else {\r
+    ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);\r
+    if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) &&\r
+        PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress) &&\r
+        (HandleNum > 1)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_ERROR;\r
+    }\r
+  }\r
+  //\r
+  // For each ip6 protocol, check interface addresses list.\r
+  //\r
+  for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {\r
+\r
+    EfiSb             = NULL;\r
+    IpXInterfaceInfo  = NULL;\r
+    IfInfoSize        = 0;\r
+\r
+    Status = gBS->HandleProtocol (\r
+                    HandleBuffer[HandleIndex],\r
+                    Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,\r
+                    (VOID **) &EfiSb\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    if (Private->IpChoice == PING_IP_CHOICE_IP6?NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress):PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {\r
+      //\r
+      // No need to match interface address.\r
+      //\r
+      break;\r
+    } else {\r
+      //\r
+      // Ip6config protocol and ip6 service binding protocol are installed\r
+      // on the same handle.\r
+      //\r
+      Status = gBS->HandleProtocol (\r
+                      HandleBuffer[HandleIndex],\r
+                      Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4ConfigProtocolGuid,\r
+                      (VOID **) &IpXCfg\r
+                      );\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_ERROR;\r
+      }\r
+      //\r
+      // Get the interface information size.\r
+      //\r
+      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+        Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                           IpXCfg,\r
+                           Ip6ConfigDataTypeInterfaceInfo,\r
+                           &IfInfoSize,\r
+                           NULL\r
+                           );\r
+      } else {\r
+        Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                           IpXCfg,\r
+                           &IfInfoSize,\r
+                           NULL\r
+                           );\r
+      }\r
+      \r
+      //\r
+      // Skip the ones not in current use.\r
+      //\r
+      if (Status == EFI_NOT_STARTED) {\r
+        continue;\r
+      }\r
+\r
+      if (Status != EFI_BUFFER_TOO_SMALL) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
+        goto ON_ERROR;\r
+      }\r
+\r
+      IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);\r
+\r
+      if (IpXInterfaceInfo == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto ON_ERROR;\r
+      }\r
+      //\r
+      // Get the interface info.\r
+      //\r
+      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+        Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                           IpXCfg,\r
+                           Ip6ConfigDataTypeInterfaceInfo,\r
+                           &IfInfoSize,\r
+                           IpXInterfaceInfo\r
+                           );\r
+      } else {\r
+        Status = ((EFI_IP4_CONFIG_PROTOCOL*)IpXCfg)->GetData (\r
+                           IpXCfg,\r
+                           &IfInfoSize,\r
+                           IpXInterfaceInfo\r
+                           );\r
+      }\r
+\r
+      if (EFI_ERROR (Status)) {\r
+        ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);\r
+        goto ON_ERROR;\r
+      }\r
+      //\r
+      // Check whether the source address is one of the interface addresses.\r
+      //\r
+      if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+        for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {\r
+\r
+          Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);\r
+          if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
+            //\r
+            // Match a certain interface address.\r
+            //\r
+            break;\r
+          }\r
+        }\r
+\r
+        if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {\r
+          //\r
+          // Found a nic handle with right interface address.\r
+          //\r
+          break;\r
+        }\r
+      } else {\r
+        //\r
+        // IP4 address check\r
+        //\r
+        if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_IPCONFIG_DATA*)IpXInterfaceInfo)->StationAddress)) {\r
+          //\r
+          // Match a certain interface address.\r
+          //\r
+          break;\r
+        }\r
+      }\r
+    }\r
+\r
+    FreePool (IpXInterfaceInfo);\r
+    IpXInterfaceInfo = NULL;\r
+  }\r
+  //\r
+  // No exact interface address matched.\r
+  //\r
+\r
+  if (HandleIndex == HandleNum) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, mSrcString);\r
+    Status = EFI_NOT_FOUND;\r
+    goto ON_ERROR;\r
+  }\r
+\r
+  Private->NicHandle = HandleBuffer[HandleIndex];\r
+\r
+  ASSERT (EfiSb != NULL);\r
+  Status = EfiSb->CreateChild (EfiSb, &Private->IpChildHandle);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+  if (Private->IpChoice == PING_IP_CHOICE_IP6) {\r
+    Status = gBS->OpenProtocol (\r
+                    Private->IpChildHandle,\r
+                    &gEfiIp6ProtocolGuid,\r
+                    &Private->IpProtocol,\r
+                    gImageHandle,\r
+                    Private->IpChildHandle,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+\r
+    ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA));\r
+\r
+    //\r
+    // Configure the ip6 instance for icmp6 packet exchange.\r
+    //\r
+    Ip6Config.DefaultProtocol   = 58;\r
+    Ip6Config.AcceptAnyProtocol = FALSE;\r
+    Ip6Config.AcceptIcmpErrors  = TRUE;\r
+    Ip6Config.AcceptPromiscuous = FALSE;\r
+    Ip6Config.TrafficClass      = 0;\r
+    Ip6Config.HopLimit          = 128;\r
+    Ip6Config.FlowLabel         = 0;\r
+    Ip6Config.ReceiveTimeout    = 0;\r
+    Ip6Config.TransmitTimeout   = 0;\r
+\r
+    IP6_COPY_ADDRESS (&Ip6Config.StationAddress,     &Private->SrcAddress);\r
+    IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress);\r
+\r
+    Status = ((EFI_IP6_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip6Config);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    Private->ProtocolPointers.Transmit  = (PING_IPX_TRANSMIT )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Transmit;\r
+    Private->ProtocolPointers.Receive   = (PING_IPX_RECEIVE  )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Receive;\r
+    Private->ProtocolPointers.Cancel    = (PING_IPX_CANCEL   )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Cancel;\r
+    Private->ProtocolPointers.Poll      = (PING_IPX_POLL     )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Poll;\r
+  } else {\r
+    Status = gBS->OpenProtocol (\r
+                    Private->IpChildHandle,\r
+                    &gEfiIp4ProtocolGuid,\r
+                    &Private->IpProtocol,\r
+                    gImageHandle,\r
+                    Private->IpChildHandle,\r
+                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_ERROR;\r
+    }\r
+\r
+\r
+    ZeroMem (&Ip4Config, sizeof (EFI_IP4_CONFIG_DATA));\r
+\r
+    //\r
+    // Configure the ip4 instance for icmp4 packet exchange.\r
+    //\r
+//    PING_IP4_COPY_ADDRESS (&Ip4Config.StationAddress,     &Private->SrcAddress);\r
+//    Ip4Config.SubnetMask.Addr[0] = 0xFF;\r
+//    Ip4Config.SubnetMask.Addr[1] = 0xFF;\r
+//    Ip4Config.SubnetMask.Addr[2] = 0xFF;\r
+//    Ip4Config.SubnetMask.Addr[3] = 0x00;\r
+    Ip4Config.DefaultProtocol   = 1;\r
+    Ip4Config.AcceptAnyProtocol = FALSE;\r
+    Ip4Config.AcceptBroadcast   = FALSE;\r
+    Ip4Config.AcceptIcmpErrors  = TRUE;\r
+    Ip4Config.AcceptPromiscuous = FALSE;\r
+    Ip4Config.DoNotFragment     = FALSE;\r
+    Ip4Config.RawData           = FALSE;\r
+    Ip4Config.ReceiveTimeout    = 0;\r
+    Ip4Config.TransmitTimeout   = 0;\r
+    Ip4Config.UseDefaultAddress = TRUE;\r
+    Ip4Config.TimeToLive        = 128;\r
+    Ip4Config.TypeOfService     = 0;\r
+\r
+    Status = ((EFI_IP4_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip4Config);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status);\r
+      goto ON_ERROR;\r
+    }\r
+\r
+    Private->ProtocolPointers.Transmit  = (PING_IPX_TRANSMIT )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Transmit;\r
+    Private->ProtocolPointers.Receive   = (PING_IPX_RECEIVE  )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Receive;\r
+    Private->ProtocolPointers.Cancel    = (PING_IPX_CANCEL   )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Cancel;\r
+    Private->ProtocolPointers.Poll      = (PING_IPX_POLL     )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Poll;  \r
+  }\r
+\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+\r
+ON_ERROR:\r
+  if (HandleBuffer != NULL) {\r
+    FreePool (HandleBuffer);\r
+  }\r
+\r
+  if (IpXInterfaceInfo != NULL) {\r
+    FreePool (IpXInterfaceInfo);\r
+  }\r
+\r
+  if ((EfiSb != NULL) && (Private->IpChildHandle != NULL)) {\r
+    EfiSb->DestroyChild (EfiSb, Private->IpChildHandle);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Destory the IP instance.\r
+\r
+  @param[in]    Private    The pointer of PING_PRIVATE_DATA.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ping6DestoryIp6Instance (\r
+  IN PING_PRIVATE_DATA    *Private\r
+  )\r
+{\r
+  EFI_STATUS                      Status;\r
+  EFI_SERVICE_BINDING_PROTOCOL    *IpSb;\r
+\r
+  gBS->CloseProtocol (\r
+         Private->IpChildHandle,\r
+         Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ProtocolGuid:&gEfiIp4ProtocolGuid,\r
+         gImageHandle,\r
+         Private->IpChildHandle\r
+         );\r
+\r
+  Status = gBS->HandleProtocol (\r
+                  Private->NicHandle,\r
+                  Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,\r
+                  (VOID **) &IpSb\r
+                  );\r
+\r
+  if (!EFI_ERROR(Status)) {\r
+    IpSb->DestroyChild (IpSb, Private->IpChildHandle);\r
+  }\r
+}\r
+\r
+/**\r
+  The Ping Process.\r
+\r
+  @param[in]   SendNumber     The send request count.\r
+  @param[in]   BufferSize     The send buffer size.\r
+  @param[in]   SrcAddress     The source address.\r
+  @param[in]   DstAddress     The destination address.\r
+  @param[in]   IpChoice       The choice between IPv4 and IPv6.\r
+\r
+  @retval SHELL_SUCCESS  The ping processed successfullly.\r
+  @retval others         The ping processed unsuccessfully.\r
+**/\r
+SHELL_STATUS\r
+EFIAPI\r
+ShellPing (\r
+  IN UINT32              SendNumber,\r
+  IN UINT32              BufferSize,\r
+  IN EFI_IPv6_ADDRESS    *SrcAddress,\r
+  IN EFI_IPv6_ADDRESS    *DstAddress,\r
+  IN UINT32              IpChoice\r
+  )\r
+{\r
+  EFI_STATUS             Status;\r
+  PING_PRIVATE_DATA      *Private;\r
+  PING_ICMPX_TX_INFO     *TxInfo;\r
+  LIST_ENTRY             *Entry;\r
+  LIST_ENTRY             *NextEntry;\r
+  SHELL_STATUS           ShellStatus;\r
+\r
+  ShellStatus = SHELL_SUCCESS;\r
+  Private     = AllocateZeroPool (sizeof (PING_PRIVATE_DATA));\r
+\r
+  if (Private == NULL) {\r
+    return (SHELL_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  Private->IpChoice    = IpChoice;\r
+  Private->Signature   = PING_PRIVATE_DATA_SIGNATURE;\r
+  Private->SendNum     = SendNumber;\r
+  Private->BufferSize  = BufferSize;\r
+  Private->RttMin      = ~((UINT64 )(0x0));\r
+  Private->Status      = EFI_NOT_READY;\r
+\r
+  CopyMem(&Private->SrcAddress, SrcAddress, sizeof(Private->SrcAddress));\r
+  CopyMem(&Private->DstAddress, DstAddress, sizeof(Private->DstAddress));\r
+\r
+  InitializeListHead (&Private->TxList);\r
+\r
+  //\r
+  // Open and configure a ip instance for us.\r
+  //\r
+  Status = PingCreateIpInstance (Private);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Print the command line itself.\r
+  //\r
+  ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_START), gShellNetwork1HiiHandle, mDstString, Private->BufferSize);\r
+  //\r
+  // Create a ipv6 token to receive the first icmp6 echo reply packet.\r
+  //\r
+  Status = Ping6ReceiveEchoReply (Private);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Create and start timer to send icmp6 echo request packet per second.\r
+  //\r
+  Status = gBS->CreateEvent (\r
+                  EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+                  TPL_CALLBACK,\r
+                  Ping6OnTimerRoutine,\r
+                  Private,\r
+                  &Private->Timer\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Create a ipv6 token to send the first icmp6 echo request packet.\r
+  //\r
+  Status = PingSendEchoRequest (Private);\r
+  //\r
+  // EFI_NOT_READY for IPsec is enable and IKE is not established.\r
+  //\r
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    if(Status == EFI_NOT_FOUND) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOSOURCE_INDO), gShellNetwork1HiiHandle, mDstString);\r
+    } else if (Status == RETURN_NO_MAPPING) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);\r
+    } else {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, Status);\r
+    }\r
+\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  Status = gBS->SetTimer (\r
+                  Private->Timer,\r
+                  TimerPeriodic,\r
+                  ONE_SECOND\r
+                  );\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    ShellStatus = SHELL_ACCESS_DENIED;\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Control the ping6 process by two factors:\r
+  // 1. Hot key\r
+  // 2. Private->Status\r
+  //   2.1. success means all icmp6 echo request packets get reply packets.\r
+  //   2.2. timeout means the last icmp6 echo reply request timeout to get reply.\r
+  //   2.3. noready means ping6 process is on-the-go.\r
+  //\r
+  while (Private->Status == EFI_NOT_READY) {\r
+    Status = Private->ProtocolPointers.Poll (Private->IpProtocol);\r
+    if (ShellGetExecutionBreakFlag()) {\r
+      Private->Status = EFI_ABORTED;\r
+      goto ON_STAT;\r
+    }\r
+  }\r
+\r
+ON_STAT:\r
+  //\r
+  // Display the statistics in all.\r
+  //\r
+  gBS->SetTimer (Private->Timer, TimerCancel, 0);\r
+\r
+  if (Private->TxCount != 0) {\r
+    ShellPrintHiiEx (\r
+      -1,\r
+      -1,\r
+      NULL,\r
+      STRING_TOKEN (STR_PING_STAT),\r
+      gShellNetwork1HiiHandle,\r
+      Private->TxCount,\r
+      Private->RxCount,\r
+      (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount,\r
+      Private->RttSum\r
+      );\r
+  }\r
+\r
+  if (Private->RxCount != 0) {\r
+    ShellPrintHiiEx (\r
+      -1,\r
+      -1,\r
+      NULL,\r
+      STRING_TOKEN (STR_PING_RTT),\r
+      gShellNetwork1HiiHandle,\r
+      Private->RttMin,\r
+      Private->RttMax,\r
+      DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)\r
+      );\r
+  }\r
+\r
+ON_EXIT:\r
+\r
+  if (Private != NULL) {\r
+\r
+    NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
+      TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);\r
+\r
+      if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) {\r
+        Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token);\r
+      }\r
+\r
+      RemoveEntryList (&TxInfo->Link);\r
+      PingDestroyTxInfo (TxInfo, Private->IpChoice);\r
+    }\r
+\r
+    if (Private->Timer != NULL) {\r
+      gBS->CloseEvent (Private->Timer);\r
+    }\r
+\r
+    if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) {\r
+      Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, &Private->RxToken);\r
+    }\r
+\r
+    if (Private->RxToken.Event != NULL) {\r
+      gBS->CloseEvent (Private->RxToken.Event);\r
+    }\r
+\r
+    if (Private->IpChildHandle != NULL) {\r
+      Ping6DestoryIp6Instance (Private);\r
+    }\r
+\r
+    FreePool (Private);\r
+  }\r
+\r
+  return ShellStatus;\r
+}\r
+\r
+/**\r
+  Function for 'ping' command.\r
+\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
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunPing (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  EFI_STATUS          Status;\r
+  SHELL_STATUS        ShellStatus;\r
+  EFI_IPv6_ADDRESS    DstAddress;\r
+  EFI_IPv6_ADDRESS    SrcAddress;\r
+  UINT64              BufferSize;\r
+  UINTN               SendNumber;\r
+  LIST_ENTRY          *ParamPackage;\r
+  CONST CHAR16        *ValueStr;\r
+  UINTN               NonOptionCount;\r
+  UINT32              IpChoice;\r
+\r
+  //\r
+  // we use IPv6 buffers to hold items... \r
+  // make sure this is enough space!\r
+  //\r
+  ASSERT(sizeof(EFI_IPv4_ADDRESS        ) <= sizeof(EFI_IPv6_ADDRESS         ));\r
+  ASSERT(sizeof(EFI_IP4_COMPLETION_TOKEN) <= sizeof(EFI_IP6_COMPLETION_TOKEN ));\r
+\r
+  IpChoice = PING_IP_CHOICE_IP4;\r
+\r
+  ShellStatus = SHELL_SUCCESS;\r
+\r
+  Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, NULL, TRUE, FALSE);\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle);\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  if (ShellCommandLineGetFlag (ParamPackage, L"-_ip6")) {\r
+    IpChoice = PING_IP_CHOICE_IP6;\r
+  }\r
+\r
+  //\r
+  // Parse the paramter of count number.\r
+  //\r
+  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");\r
+  if (ValueStr != NULL) {\r
+    SendNumber = ShellStrToUintn (ValueStr);\r
+\r
+    //\r
+    // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
+    //\r
+    if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+  } else {\r
+    SendNumber = DEFAULT_SEND_COUNT;\r
+  }\r
+  //\r
+  // Parse the paramter of buffer size.\r
+  //\r
+  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");\r
+  if (ValueStr != NULL) {\r
+    BufferSize = ShellStrToUintn (ValueStr);\r
+\r
+    //\r
+    // ShellStrToUintn will return 0 when input is 0 or an invalid input string.\r
+    //\r
+    if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+  } else {\r
+    BufferSize = DEFAULT_BUFFER_SIZE;\r
+  }\r
+\r
+  ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS));\r
+  ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));\r
+\r
+  //\r
+  // Parse the paramter of source ip address.\r
+  //\r
+  ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");\r
+  if (ValueStr != NULL) {\r
+    mSrcString = ValueStr;\r
+    if (IpChoice == PING_IP_CHOICE_IP6) {\r
+      Status = NetLibStrToIp6 (ValueStr, &SrcAddress);\r
+    } else {\r
+      Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+  //\r
+  // Parse the paramter of destination ip address.\r
+  //\r
+  NonOptionCount = ShellCommandLineGetCount(ParamPackage);\r
+  if (NonOptionCount < 2) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle);\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+  if (NonOptionCount > 2) {\r
+    ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle);\r
+    ShellStatus = SHELL_INVALID_PARAMETER;\r
+    goto ON_EXIT;\r
+  }\r
+  ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);\r
+  if (ValueStr != NULL) {\r
+    mDstString = ValueStr;\r
+    if (IpChoice == PING_IP_CHOICE_IP6) {\r
+      Status = NetLibStrToIp6 (ValueStr, &DstAddress);\r
+    } else {\r
+      Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);\r
+    }\r
+    if (EFI_ERROR (Status)) {\r
+      ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellNetwork1HiiHandle, ValueStr);\r
+      ShellStatus = SHELL_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+  }\r
+  //\r
+  // Get frequency to calculate the time from ticks.\r
+  //\r
+  Status = GetFrequency ();\r
+\r
+  if (EFI_ERROR(Status)) {\r
+    goto ON_EXIT;\r
+  }\r
+  //\r
+  // Enter into ping process.\r
+  //\r
+  ShellStatus = ShellPing (\r
+             (UINT32)SendNumber,\r
+             (UINT32)BufferSize,\r
+             &SrcAddress,\r
+             &DstAddress,\r
+             IpChoice\r
+             );\r
+\r
+ON_EXIT:\r
+  ShellCommandLineFreeVarList (ParamPackage);\r
+  return ShellStatus;\r
+}\r
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c
new file mode 100644 (file)
index 0000000..d8fa88d
--- /dev/null
@@ -0,0 +1,94 @@
+/** @file\r
+  Main file for NULL named library for network1 shell command functions.\r
+\r
+  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+#include "UefiShellNetwork1CommandsLib.h"\r
+\r
+CONST CHAR16 gShellNetwork1FileName[] = L"ShellCommands";\r
+EFI_HANDLE gShellNetwork1HiiHandle = NULL;\r
+STATIC CONST EFI_GUID gShellNetwork1HiiGuid = \\r
+  { \\r
+    0xf3d301bb, 0xf4a5, 0x45a8, { 0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae } \\r
+  };\r
+\r
+/**\r
+  return the file name of the help text file if not using HII.\r
+\r
+  @return The string pointer to the file name.\r
+**/\r
+CONST CHAR16*\r
+EFIAPI\r
+ShellCommandGetManFileNameNetwork1 (\r
+  VOID\r
+  )\r
+{\r
+  return (gShellNetwork1FileName);\r
+}\r
+\r
+/**\r
+  Constructor for the Shell Network1 Commands library.\r
+\r
+  Install the handlers for Network1 UEFI Shell 2.0 profile commands.\r
+\r
+  @param ImageHandle            The image handle of the process.\r
+  @param SystemTable            The EFI System Table pointer.\r
+\r
+  @retval EFI_SUCCESS           The shell command handlers were installed sucessfully.\r
+  @retval EFI_UNSUPPORTED       The shell level required was not found.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellNetwork1CommandsLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  gShellNetwork1HiiHandle = NULL;\r
+\r
+  //\r
+  // check our bit of the profiles mask\r
+  //\r
+  if ((PcdGet8(PcdShellProfileMask) & BIT3) == 0) {\r
+    return (EFI_UNSUPPORTED);\r
+  }\r
+\r
+  gShellNetwork1HiiHandle = HiiAddPackages (&gShellNetwork1HiiGuid, gImageHandle, UefiShellNetwork1CommandsLibStrings, NULL);\r
+  if (gShellNetwork1HiiHandle == NULL) {\r
+    return (EFI_DEVICE_ERROR);\r
+  }\r
+  //\r
+  // install our shell command handlers\r
+  //\r
+  ShellCommandRegisterCommandName(L"ping",    ShellCommandRunPing     , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_PING));\r
+  ShellCommandRegisterCommandName(L"ifconfig",ShellCommandRunIfconfig , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_IFCONFIG));\r
+\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
+/**\r
+  Destructor for the library.  free any resources.\r
+\r
+  @param ImageHandle            The image handle of the process.\r
+  @param SystemTable            The EFI System Table pointer.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellNetwork1CommandsLibDestructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+  if (gShellNetwork1HiiHandle != NULL) {\r
+    HiiRemovePackages(gShellNetwork1HiiHandle);\r
+  }\r
+  return (EFI_SUCCESS);\r
+}\r
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h
new file mode 100644 (file)
index 0000000..144063c
--- /dev/null
@@ -0,0 +1,79 @@
+/** @file\r
+  header file for NULL named library for network1 shell command functions.\r
+\r
+  Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#if !defined (_UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_)\r
+#define _UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_\r
+\r
+#include <Uefi.h>\r
+#include <ShellBase.h>\r
+\r
+#include <Protocol/Cpu.h>\r
+#include <Protocol/ServiceBinding.h>\r
+#include <Protocol/Ip6.h>\r
+#include <Protocol/Ip6Config.h>\r
+#include <Protocol/Ip4.h>\r
+#include <Protocol/Ip4Config.h>\r
+#include <Protocol/HiiConfigAccess.h>\r
+#include <Protocol/HiiConfigRouting.h>\r
+#include <Protocol/Arp.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Library/ShellCommandLib.h>\r
+#include <Library/ShellLib.h>\r
+#include <Library/SortLib.h>\r
+#include <Library/UefiLib.h>\r
+#include <Library/UefiRuntimeServicesTableLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/HiiLib.h>\r
+#include <Library/NetLib.h>\r
+#include <Library/DevicePathLib.h>\r
+#include <Library/PrintLib.h>\r
+\r
+#include <Guid/NicIp4ConfigNvData.h>\r
+\r
+extern EFI_HANDLE gShellNetwork1HiiHandle;\r
+\r
+/**\r
+  Function for 'ping' command.\r
+\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
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunPing (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  );\r
+\r
+/**\r
+  Function for 'ifconfig' command.\r
+\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
+SHELL_STATUS\r
+EFIAPI\r
+ShellCommandRunIfconfig (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  );\r
+\r
+#endif\r
+\r
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
new file mode 100644 (file)
index 0000000..51dca82
--- /dev/null
@@ -0,0 +1,75 @@
+##  @file\r
+# Provides shell network1 functions\r
+#\r
+# Copyright (c) 2010, Intel Corporation. All rights reserved. <BR>\r
+#\r
+#  This program and the accompanying materials\r
+#  are licensed and made available under the terms and conditions of the BSD License\r
+#  which accompanies this distribution. The full text of the license may be found at\r
+#  http://opensource.org/licenses/bsd-license.php\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
+\r
+[Defines]\r
+  INF_VERSION                    = 0x00010006\r
+  BASE_NAME                      = UefiShellNetwork1CommandsLib\r
+  FILE_GUID                      = 9A929F7E-3861-45ce-87AB-7371219AE255\r
+  MODULE_TYPE                    = UEFI_DRIVER\r
+  VERSION_STRING                 = 1.0\r
+  LIBRARY_CLASS                  = NULL|UEFI_APPLICATION UEFI_DRIVER\r
+  CONSTRUCTOR                    = ShellNetwork1CommandsLibConstructor\r
+  DESTRUCTOR                     = ShellNetwork1CommandsLibDestructor\r
+\r
+[Sources.common]\r
+  UefiShellNetwork1CommandsLib.uni\r
+  UefiShellNetwork1CommandsLib.c\r
+  UefiShellNetwork1CommandsLib.h\r
+  Ping.c\r
+  Ifconfig.c\r
+\r
+[Sources.IA32]\r
+  Ia32/Tsc.c\r
+\r
+[Sources.X64]\r
+  X64/Tsc.c\r
+\r
+[Sources.IPF]\r
+  Ipf/Itc.c\r
+\r
+[Packages]\r
+  MdePkg/MdePkg.dec\r
+  ShellPkg/ShellPkg.dec\r
+  MdeModulePkg/MdeModulePkg.dec\r
+\r
+[LibraryClasses]\r
+  MemoryAllocationLib\r
+  BaseLib\r
+  BaseMemoryLib\r
+  DebugLib\r
+  ShellCommandLib\r
+  ShellLib\r
+  UefiLib\r
+  UefiRuntimeServicesTableLib\r
+  UefiBootServicesTableLib\r
+  PcdLib\r
+  HiiLib\r
+  FileHandleLib\r
+  NetLib\r
+\r
+[Guids]\r
+\r
+[Pcd]\r
+  gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask # ALWAYS_CONSUMED\r
+\r
+[Protocols]\r
+  gEfiCpuArchProtocolGuid                       # ALWAYS_CONSUMED\r
+  gEfiIp6ProtocolGuid                           # SOMETIMES_CONSUMED\r
+  gEfiIp6ServiceBindingProtocolGuid             # SOMETIMES_CONSUMED\r
+  gEfiIp6ConfigProtocolGuid                     # SOMETIMES_CONSUMED\r
+\r
+  gEfiIp6ProtocolGuid                           # SOMETIMES_CONSUMED\r
+  gEfiIp6ServiceBindingProtocolGuid             # SOMETIMES_CONSUMED\r
+  gEfiIp6ConfigProtocolGuid                     # SOMETIMES_CONSUMED
\ No newline at end of file
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
new file mode 100644 (file)
index 0000000..f2303dc
Binary files /dev/null and b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni differ
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/X64/Tsc.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/X64/Tsc.c
new file mode 100644 (file)
index 0000000..b3e7bdb
--- /dev/null
@@ -0,0 +1,28 @@
+/** @file\r
+  The implement to read TSC in X64 platform.\r
+\r
+  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <Library/BaseLib.h>\r
+\r
+/**\r
+  Reads and returns the current value of Time Stamp Counter (TSC).\r
+\r
+  @return The current value of TSC\r
+\r
+**/\r
+UINT64\r
+ReadTime ()\r
+{\r
+  return AsmReadTsc ();\r
+}\r