SHEL7
authorhfang <hfang@0aefa8ac-fc23-0410-b7a3-bf826d37e4c2>
Thu, 7 Sep 2006 06:16:55 +0000 (06:16 +0000)
committerhfang <hfang@0aefa8ac-fc23-0410-b7a3-bf826d37e4c2>
Thu, 7 Sep 2006 06:16:55 +0000 (06:16 +0000)
git-svn-id: https://efi-shell.tianocore.org/svn/efi-shell/trunk/Shell@20 0aefa8ac-fc23-0410-b7a3-bf826d37e4c2

16 files changed:
EDK_Snapshot.txt
IfConfig/IfConfig.c [new file with mode: 0644]
IfConfig/IfConfig.h [new file with mode: 0644]
IfConfig/IfConfig.inf [new file with mode: 0644]
IfConfig/IfConfigStrings.uni [new file with mode: 0644]
IfConfig/ShellNetHelper.c [new file with mode: 0644]
IfConfig/ShellNetHelper.h [new file with mode: 0644]
Library/DPath.c
Ping/Ping.c [new file with mode: 0644]
Ping/Ping.h [new file with mode: 0644]
Ping/Ping.inf [new file with mode: 0644]
Ping/PingStrings.uni [new file with mode: 0644]
SmbiosView/LibSmbios.h
SmbiosView/PrintInfo.c
comp/comp.c
shellenv/parsecmd.c

index 7c73d86..9c47365 100644 (file)
@@ -1,5 +1,5 @@
 Notes:
-  This EFI Shell release package has been tested on the 2006-08-07's EDK which snapshot
-is Edk-Dev-Snapshot-200600807, User can get this version EDK from the following URL:
-  http://edk.tianocore.org/files/documents/16/265/Edk-Dev-Snapshot-20060807.zip
+  This EFI Shell release package has been tested on the 2006-09-04's EDK which snapshot
+is Edk-Dev-Snapshot-20060904, User can get this version EDK from the following URL:
+  http://edk.tianocore.org/files/documents/16/273/Edk-Dev-Snapshot-20060904.zip
   We don't guarantee this package can work correctly on the other EDK snapshot.
\ No newline at end of file
diff --git a/IfConfig/IfConfig.c b/IfConfig/IfConfig.c
new file mode 100644 (file)
index 0000000..c9935a4
--- /dev/null
@@ -0,0 +1,1208 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation                                                         
+All rights reserved. This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution. The full text of the license may be found at         
+http://opensource.org/licenses/bsd-license.php                                            
+                                                                                          
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+Module Name:
+
+  IfConfig.c
+  
+Abstract:
+
+  Shell command "IfConfig"
+
+--*/
+#include "IfConfig.h"
+
+#include STRING_DEFINES_FILE
+extern UINT8 STRING_ARRAY_NAME[];
+
+EFI_HII_HANDLE  HiiHandle;
+
+EFI_GUID  EfiIfConfigGuid = EFI_IFCONFIG_GUID;
+
+SHELL_VAR_CHECK_ITEM  IfConfigCheckList[] = {
+  {
+    L"-b",
+    0,
+    0,
+    FlagTypeSingle
+  },
+  {
+    L"-s",
+    0x1,
+    0xe,
+    FlagTypeSingle
+  },
+  {
+    L"-l",
+    0x2,
+    0xd,
+    FlagTypeSingle
+  },
+  {
+    L"-c",
+    0x4,
+    0xb,
+    FlagTypeSingle
+  },
+  {
+    L"-?",
+    0x8,
+    0x7,
+    FlagTypeSingle
+  },
+  {
+    NULL,
+    0,
+    0,
+    0
+  }
+};
+
+EFI_LIST_ENTRY                  NicInfoList;
+BOOLEAN                         ArpResolved;
+BOOLEAN                         Timeout;
+
+NIC_INFO*
+IfconfigFindNicByName (
+  IN UINT16                     *Name
+  )
+/*++
+
+Routine Description:
+
+  Find the NIC_INFO by the specified nic name.
+
+Arguments:
+
+  Name - Pointer to the string containing the NIC name.
+
+Returns:
+
+  Pointer to the NIC_INFO if there is a NIC_INFO named by Name, otherwise NULL.
+
+--*/
+{
+  EFI_LIST_ENTRY                *Entry;
+  NIC_INFO                      *Info;
+
+  EFI_LIST_FOR_EACH (Entry, &NicInfoList) {
+    Info = _CR (Entry, NIC_INFO, Link);
+
+    if (StriCmp (Name, Info->Name) == 0) {
+      return Info;
+    }
+  }
+
+  return NULL;
+}
+
+VOID
+PrintMac (
+  IN CHAR16                     *Prefix,
+  IN EFI_MAC_ADDRESS            *Mac
+  )
+/*++
+
+Routine Description:
+
+  Print the specified mac address with the Prefix message.
+
+Arguments:
+
+  Prefix - Pointer to some prefix message.
+  Mac    - Pointer to the mac address.
+
+Returns:
+
+  None.
+
+--*/
+{
+  if (Prefix != NULL) {
+    Print (Prefix);
+  }
+  
+  PrintToken (
+    STRING_TOKEN (STR_IFCONFIG_SHOW_MAC_ADDR),
+    HiiHandle,
+    Mac->Addr[0], 
+    Mac->Addr[1], 
+    Mac->Addr[2],
+    Mac->Addr[3], 
+    Mac->Addr[4], 
+    Mac->Addr[5]
+    );
+}
+
+VOID
+PrintIp (
+  IN CHAR16                     *Prefix,
+  IN EFI_IPv4_ADDRESS           *Ip4 
+  )
+/*++
+
+Routine Description:
+
+  Print the specified IPv4 address with the Prefix message.
+
+Arguments:
+
+  Prefix - Pointer to some prefix message.
+  Ip4    - Pointer to the IPv4 address.
+
+Returns:
+
+  None.
+
+--*/
+{
+  if (Prefix != NULL) {
+    Print (Prefix);
+  }
+
+  PrintToken (
+    STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
+    HiiHandle,
+    Ip4->Addr[0],
+    Ip4->Addr[1],
+    Ip4->Addr[2],
+    Ip4->Addr[3]
+    );
+}
+
+EFI_STATUS
+IfconfigGetAllNicInfo (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Get all Nic's information through Ip4Config protocol.
+
+Arguments:
+
+  None.
+
+Returns:
+
+  EFI_SUCCESS - All the nic information is collected.
+  other       - Some error occurs.
+
+--*/
+{
+  EFI_NIC_IP4_CONFIG_PROTOCOL   *NicIp4Config;
+  EFI_IP4_CONFIG_PROTOCOL       *Ip4Config;
+  NIC_INFO                      *NicInfo;
+  NIC_IP4_CONFIG_INFO           *NicConfig;
+  EFI_HANDLE                    *Handles;
+  UINTN                         HandleCount;
+  UINT32                        Index;
+  UINTN                         Len;
+  EFI_STATUS                    Status;
+
+  NicIp4Config = NULL;
+  Ip4Config    = NULL;
+  NicInfo      = NULL;
+  NicConfig    = NULL;
+  Handles      = NULL;
+
+  InitializeListHead (&NicInfoList);
+
+  //
+  // Locate the handles which has NicIp4Config installed.
+  //
+  Status = BS->LocateHandleBuffer (
+                ByProtocol,
+                &gEfiNicIp4ConfigProtocolGuid,
+                NULL,
+                &HandleCount,
+                &Handles
+                );
+  if (EFI_ERROR (Status) || (HandleCount == 0)) {
+    PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_LOC_PROT_ERR_EX), HiiHandle, L"IfConfig", L"Ip4Config protocol");
+    
+    return EFI_NOT_FOUND;
+  }
+
+  for (Index = 0; Index < HandleCount; Index++) {
+    //
+    // Open the NicIp4Config and Ip4Config protocols
+    //
+    Status = BS->HandleProtocol (
+                   Handles[Index],
+                   &gEfiNicIp4ConfigProtocolGuid,
+                   (VOID **) &NicIp4Config
+                   );
+    
+    if (EFI_ERROR (Status)) {
+      goto ON_ERROR;
+    }
+
+    Status = BS->HandleProtocol (
+                   Handles[Index],
+                   &gEfiIp4ConfigProtocolGuid,
+                   (VOID **) &Ip4Config
+                   );
+    
+    if (EFI_ERROR (Status)) {
+      goto ON_ERROR;
+    }
+
+    //
+    // Get the Nic IP4 configure through the NicIp4Config protocol
+    //
+    Len    = 0;
+    Status = NicIp4Config->GetInfo (NicIp4Config, &Len, NULL);
+
+    if (Status == EFI_BUFFER_TOO_SMALL) {
+      NicConfig = AllocatePool (Len);
+  
+      if (NicConfig == NULL) {
+  
+        Status = EFI_OUT_OF_RESOURCES;
+        goto ON_ERROR;
+      }
+
+      Status = NicIp4Config->GetInfo (NicIp4Config, &Len, NicConfig); 
+
+      if (EFI_ERROR (Status)) {
+
+        goto ON_ERROR;
+      }
+    } else if (Status != EFI_NOT_FOUND) {     
+      
+      goto ON_ERROR;
+    }
+
+    //
+    // Add the Nic's info to the global NicInfoList.
+    //
+    NicInfo = AllocatePool (sizeof (NIC_INFO));
+
+    if (NicInfo == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_ERROR;
+    }
+    
+    NicInfo->Handle       = Handles[Index];
+    NicInfo->NicIp4Config = NicIp4Config;
+    NicInfo->Ip4Config    = Ip4Config;
+    NicInfo->ConfigInfo   = NicConfig;
+    
+    Status = NicIp4Config->GetName (NicIp4Config, NicInfo->Name, &NicInfo->NicAddress);
+
+    if (EFI_ERROR (Status)) {
+      goto ON_ERROR;
+    }
+
+    InsertTailList (&NicInfoList, &NicInfo->Link);
+    
+    NicInfo   = NULL;
+    NicConfig = NULL;
+  }
+
+  FreePool (Handles);
+  return EFI_SUCCESS;
+  
+ON_ERROR:
+  if (NicInfo != NULL) {
+    FreePool (NicInfo);
+  }
+
+  if (NicConfig != NULL) {
+    FreePool (NicConfig);
+  }
+
+  FreePool (Handles);
+
+  //
+  // Return EFI_SUCCESS if we get at least some NIC's IP configure.
+  //
+  return (Index != 0) ? EFI_SUCCESS: Status;
+}
+
+EFI_STATUS
+StrToIp (
+  IN  CHAR16                    *String,
+  OUT EFI_IPv4_ADDRESS          *Ip
+  )
+/*++
+
+Routine Description:
+
+  Convert a string into an IPv4 address.
+
+Arguments:
+
+  String - Pointer to the string containing an IPv4 address.
+  Ip     - Pointer to the storage for the IPv4 address.
+
+Returns:
+
+  EFI_SUCCESS           - The string is converted into an IPv4 address.
+  EFI_INVALID_PARAMETER - The string contains an invalid address.
+
+--*/
+{
+  EFI_IPv4_ADDRESS              IpAddr;
+  UINT32                        Index;
+  UINTN                         Byte;
+  CHAR16                        Number[8];
+  CHAR16                        *NumPtr;
+
+  EFI_IP4_TO_U32 (IpAddr) = 0;
+  if (!SHELL_IS_DIGIT (*String)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  for (Index = 0; Index < 4; Index++) {
+    //
+    // Copy the number to name buffer
+    //
+    NumPtr  = Number;
+    while (SHELL_IS_DIGIT (*String)) {
+      *NumPtr = *String;
+      NumPtr++;
+      String++;
+    } 
+    
+    *NumPtr = 0;
+    Byte    = Atoi (Number);
+    if (Byte > 255) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    IpAddr.Addr[Index]  = (UINT8) Byte;
+
+    if ((*String != '.') || !SHELL_IS_DIGIT (*(String + 1))) {
+      break;
+    }
+
+    String++;
+  }
+
+  if (Index != 3) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  *Ip = IpAddr;
+  return EFI_SUCCESS;
+}
+
+
+VOID
+EFIAPI
+IfconfigOnArpResolved (
+  IN EFI_EVENT                  Event,
+  IN VOID                       *Context
+  )
+/*++
+
+Routine Description:
+
+  The callback function for the Arp address resolved event.
+
+Arguments:
+
+  Event   - The event this function is registered to.
+  Context - The context registered to the event.
+
+Returns:
+
+  None.
+
+--*/
+{
+  ARP_REQUEST                   *Request;
+  UINT8                         Index;
+
+  Request = (ARP_REQUEST *) Context;
+  ASSERT (Request != NULL);
+
+  Request->Duplicate = FALSE;
+  
+  if (SHELL_MEM_EQUAL (&Request->LocalMac, &Request->DestMac, Request->MacLen)) {
+    PrintIp (L"IfConfig: the interface is already configured with", &Request->DestIp.v4);
+    ArpResolved = TRUE;
+    return;
+  }
+  
+  for (Index = 0; Index < Request->MacLen; Index++) {
+    if (Request->DestMac.Addr[Index] != 0) {
+      Request->Duplicate = TRUE;
+    }
+  }
+
+  if (Request->Duplicate) {
+    PrintMac (L"IfConfig: IP address conflict with:", &Request->DestMac);    
+  }
+
+  ArpResolved = TRUE;
+  return ;
+}
+
+BOOLEAN
+IfconfigIsIpDuplicate (
+  IN  NIC_INFO                  *NicInfo,
+  IN  IP4_ADDR                  IpAddr,
+  IN  EFI_HANDLE                Image
+  )
+/*++
+
+Routine Description:
+
+  Check whether the address to be configured conflicts with other hosts.
+
+Arguments:
+
+  NicInfo - Pointer to the NIC_INFO of the Nic to be configured.
+  IpAddr  - The IPv4 address to be configured to the Nic.
+  Image   - The image handle.
+
+Returns:
+
+  TRUE if some other host already uses the IpAddr, otherwise FALSE.
+
+--*/
+{
+  EFI_ARP_PROTOCOL              *Arp;
+  EFI_ARP_CONFIG_DATA           ArpCfgData;
+  EFI_HANDLE                    ArpHandle;
+  ARP_REQUEST                   Request;
+  EFI_STATUS                    Status;
+
+  Arp           = NULL;
+  ArpHandle     = NULL;
+  ZeroMem (&Request, sizeof (ARP_REQUEST));
+
+  Status = ShellCreateServiceChild (
+             NicInfo->Handle,
+             Image, 
+             &gEfiArpServiceBindingProtocolGuid,
+             &ArpHandle
+             );
+
+  if (EFI_ERROR (Status)) {
+    return FALSE;
+  }
+
+  Status = BS->OpenProtocol (
+                 ArpHandle,
+                 &gEfiArpProtocolGuid,
+                 (VOID**)&Arp,
+                 Image,
+                 ArpHandle,
+                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                 );
+
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Set up the Arp requests
+  //
+  EFI_IP4_TO_U32 (Request.DestIp.v4)  = IpAddr;
+  EFI_IP4_TO_U32 (Request.LocalIp.v4) = 0xffffffff;
+  Request.LocalMac                    = NicInfo->NicAddress.MacAddr;
+  Request.MacLen                      = NicInfo->NicAddress.Len;
+  
+  Status = BS->CreateEvent (
+                 EFI_EVENT_NOTIFY_SIGNAL,
+                 EFI_TPL_CALLBACK,
+                 IfconfigOnArpResolved,
+                 (VOID *) &Request,
+                 &Request.OnResolved
+                 );
+  
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+  
+  ArpCfgData.SwAddressType    = 0x0800;
+  ArpCfgData.SwAddressLength  = 4;
+  ArpCfgData.StationAddress   = &Request.LocalIp;
+  ArpCfgData.EntryTimeOut     = 0;
+  ArpCfgData.RetryCount       = 3;
+  ArpCfgData.RetryTimeOut     = 0;
+  
+  Status = Arp->Configure (Arp, &ArpCfgData);
+  
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  Status = Arp->Request (
+                  Arp,
+                  &Request.DestIp,
+                  Request.OnResolved,
+                  &Request.DestMac
+                  );
+  
+  if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
+    goto ON_EXIT;
+  }
+
+  while (!ArpResolved) {
+    
+  }
+
+
+ON_EXIT:
+  if (Request.OnResolved != NULL) {
+    BS->CloseEvent (Request.OnResolved);
+  }
+
+  ShellDestroyServiceChild (
+    NicInfo->Handle, 
+    Image, 
+    &gEfiArpServiceBindingProtocolGuid, 
+    ArpHandle
+    );
+
+  return Request.Duplicate;
+}
+
+VOID
+EFIAPI
+TimeoutToGetMap (
+  EFI_EVENT      Event,
+  VOID           *Context
+  )
+/*++
+
+Routine Description:
+
+  The callback function for the timer event used to get map.
+
+Arguments:
+
+  Event   - The event this function is registered to.
+  Context - The context registered to the event.
+
+Returns:
+
+  None.
+
+--*/
+{
+  Timeout = TRUE;
+  return ;
+}
+
+EFI_STATUS
+IfconfigStartIp4(
+  IN NIC_INFO                   *NicInfo,
+  IN EFI_HANDLE                 Image
+  )
+/*++
+
+Routine Description:
+
+  Create an IP child, use it to start the auto configuration, then destory it.
+
+Arguments:
+
+  NicInfo - Pointer to the NIC_INFO of the Nic to be configured.
+  Image   - The image handle.
+
+Returns:
+
+  EFI_SUCCESS - The configuration is done.
+  other       - Some error occurs.
+
+--*/
+{
+  EFI_IP4_PROTOCOL              *Ip4;
+  EFI_HANDLE                    Ip4Handle;
+  EFI_HANDLE                    TimerToGetMap;
+  EFI_IP4_CONFIG_DATA           Ip4ConfigData;
+  EFI_IP4_MODE_DATA             Ip4Mode;
+  EFI_STATUS                    Status;
+
+  //
+  // Get the Ip4ServiceBinding Protocol
+  //
+  Ip4Handle    = NULL;
+  Ip4          = NULL;
+  TimerToGetMap = NULL;
+
+  PrintToken (STRING_TOKEN (STR_IFCONFIG_START_SET_ADDR), HiiHandle);
+
+  Status = ShellCreateServiceChild (
+             NicInfo->Handle,
+             Image,
+             &gEfiIp4ServiceBindingProtocolGuid,
+             &Ip4Handle
+             );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = BS->OpenProtocol (
+                 Ip4Handle,
+                 &gEfiIp4ProtocolGuid,
+                 (VOID **) &Ip4,
+                 NicInfo->Handle,
+                 Image,
+                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                 );
+
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  Ip4ConfigData.DefaultProtocol          = EFI_IP_PROTO_ICMP;
+  Ip4ConfigData.AcceptAnyProtocol        = FALSE;
+  Ip4ConfigData.AcceptIcmpErrors         = FALSE;
+  Ip4ConfigData.AcceptBroadcast          = FALSE;
+  Ip4ConfigData.AcceptPromiscuous        = FALSE;
+  Ip4ConfigData.UseDefaultAddress        = TRUE;
+  EFI_IP4_TO_U32 (Ip4ConfigData.StationAddress) = 0;
+  EFI_IP4_TO_U32 (Ip4ConfigData.SubnetMask)     = 0;
+  Ip4ConfigData.TypeOfService            = 0;
+  Ip4ConfigData.TimeToLive               = 1;
+  Ip4ConfigData.DoNotFragment            = FALSE;
+  Ip4ConfigData.RawData                  = FALSE;
+  Ip4ConfigData.ReceiveTimeout           = 0;
+  Ip4ConfigData.TransmitTimeout          = 0;
+
+  Status = Ip4->Configure (Ip4, &Ip4ConfigData);
+
+  if (Status == EFI_NO_MAPPING) {
+    Timeout = FALSE;
+    Status  = BS->CreateEvent (
+                    EFI_EVENT_NOTIFY_SIGNAL | EFI_EVENT_TIMER,
+                    EFI_TPL_CALLBACK - 1,
+                    TimeoutToGetMap,
+                    NULL,
+                    &TimerToGetMap
+                    );
+    
+    if (EFI_ERROR (Status)) {
+      goto ON_EXIT;
+    }
+    
+    Status = BS->SetTimer (
+                   TimerToGetMap,
+                   TimerRelative,
+                   MultU64x32 (SEC_TO_NS, 5)
+                   );
+    
+    if (EFI_ERROR (Status)) {
+      goto ON_EXIT;
+    }
+
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_WAIT_SET_DONE), HiiHandle);
+    
+    while (!Timeout) {
+      Ip4->Poll (Ip4);
+  
+      if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && 
+          Ip4Mode.IsConfigured) {       
+        break;
+      }
+    }    
+  }
+
+  Status = Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL);
+
+  if ((Status == EFI_SUCCESS) && Ip4Mode.IsConfigured) {
+    PrintIp (L"The default address is: ", &Ip4Mode.ConfigData.StationAddress);  
+  }
+  
+ON_EXIT: 
+
+  if (EFI_ERROR (Status)) {
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_GET_DEF_ADDR_FAIL), HiiHandle);
+  }
+
+  if (TimerToGetMap != NULL) {
+    BS->SetTimer (TimerToGetMap, TimerCancel, 0);
+    BS->CloseEvent (TimerToGetMap);
+  }
+
+  ShellDestroyServiceChild (
+    NicInfo->Handle,
+    Image,
+    &gEfiIp4ServiceBindingProtocolGuid,
+    Ip4Handle
+    );
+  
+  return Status;
+}
+
+EFI_STATUS 
+IfconfigSetNicAddr (
+  IN UINTN                      Argc,
+  IN SHELL_ARG_LIST             *VarList,
+  IN EFI_HANDLE                 Image
+  )
+/*++
+
+Routine Description:
+
+  Set the address for the specified nic.
+
+Arguments:
+
+  Argc    - Count of the passed in VarList.
+  VarList - The command line arguments for the set operation.
+  Image   - The image handle.
+
+Returns:
+
+  EFI_SUCCESS - The address set operation is done.
+  other       - Some error occurs.
+
+--*/
+{
+  NIC_IP4_CONFIG_INFO           *Config;
+  NIC_IP4_CONFIG_INFO           *OldConfig;
+  EFI_IPv4_ADDRESS              Ip;
+  EFI_IPv4_ADDRESS              Mask;
+  EFI_IPv4_ADDRESS              Gateway;
+  NIC_INFO                      *Info;
+  BOOLEAN                       Perment;
+  EFI_STATUS                    Status;
+  
+  Info = IfconfigFindNicByName (VarList->VarStr);
+
+  if (Info == NULL) {
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_INTERFACE_NOT_FOUND), HiiHandle, VarList->VarStr);
+    return EFI_NOT_FOUND;
+  }
+
+  Config = AllocateZeroPool (sizeof (NIC_IP4_CONFIG_INFO) + sizeof (EFI_IP4_ROUTE_TABLE));
+  if (Config == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  OldConfig = Info->ConfigInfo;
+  Perment   = FALSE;
+  Status    = EFI_INVALID_PARAMETER;
+
+  VarList = VarList->Next;
+  StrUpr (VarList->VarStr);
+
+  if (StrCmp (VarList->VarStr, L"DHCP") == 0) {
+    //
+    // Validate the parameter for DHCP, two valid forms: eth0 DHCP and eth0 DHCP perment
+    //
+    if ((Argc != 2) && (Argc!= 3)) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+      goto ON_EXIT;
+    }
+
+    if (Argc == 3) {
+      VarList = VarList->Next;
+      StrUpr (VarList->VarStr);
+      if (StrCmp (VarList->VarStr, L"PERMENT") != 0) {
+        PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+        goto ON_EXIT;
+      }
+
+      Perment = TRUE;
+    }
+
+    if ((OldConfig != NULL) && (OldConfig->Source == IP4_CONFIG_SOURCE_DHCP) &&
+        (OldConfig->Perment == Perment)) {
+
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_INTERFACE_CONFIGURED), HiiHandle, Info->Name);
+      Status = EFI_ALREADY_STARTED;
+      goto ON_EXIT;
+    }
+
+    Config->Source = IP4_CONFIG_SOURCE_DHCP;
+  } else if (StrCmp (VarList->VarStr, L"STATIC") == 0) {
+    //
+    // validate the parameter, two forms: eth0 static IP NETMASK GATEWAY and
+    // eth0 static IP NETMASK GATEWAY perment
+    //
+    if ((Argc != 5) && (Argc != 6)) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+      goto ON_EXIT;
+    }
+
+    VarList = VarList->Next;
+    if (EFI_ERROR (StrToIp (VarList->VarStr, &Ip))) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), HiiHandle, VarList->VarStr);
+      goto ON_EXIT;
+    }
+
+    VarList = VarList->Next;
+    if (EFI_ERROR (StrToIp (VarList->VarStr, &Mask))) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), HiiHandle, VarList->VarStr);
+      goto ON_EXIT;
+    }
+
+    VarList = VarList->Next;
+    if (EFI_ERROR (StrToIp (VarList->VarStr, &Gateway))) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_INVALID_IP_STR), HiiHandle, VarList->VarStr);
+      goto ON_EXIT;
+    }
+
+    if (Argc == 6) {
+      VarList = VarList->Next;
+      StrUpr (VarList->VarStr);
+
+      if (StrCmp (VarList->VarStr, L"PERMENT") != 0) {
+        PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+        goto ON_EXIT;
+      }
+
+      Perment = TRUE;
+    }
+
+    if ((EFI_IP4_TO_U32 (Ip) == 0) || (EFI_IP4_TO_U32 (Mask) == 0) ||
+        !ShellIp4IsUnicast (EFI_IP4_NTOHL (Ip), EFI_IP4_NTOHL (Mask))) {
+
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_INVALID_ADDR_PAIR), HiiHandle);
+      goto ON_EXIT;
+    }
+
+    if (!IP4_EQUAL_MASK (EFI_IP4_NTOHL (Ip), EFI_IP4_NTOHL (Gateway), EFI_IP4_NTOHL (Mask)) ||
+        !ShellIp4IsUnicast (EFI_IP4_NTOHL (Gateway), EFI_IP4_NTOHL (Mask))) {
+        
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), HiiHandle);
+      goto ON_EXIT;
+    }
+
+    //
+    // Set the configuration up, two route table entries are added:
+    // one for the direct connected network, and another for the 
+    // default gateway. Remember, some structure members are cleared
+    // by AllocateZeroPool
+    //
+    Config->Source = IP4_CONFIG_SOURCE_STATIC;
+    Config->Ip4Info.StationAddress = Ip;
+    Config->Ip4Info.SubnetMask     = Mask;
+    Config->Ip4Info.RouteTableSize = 2;
+    Config->Ip4Info.RouteTable[0].SubnetAddress  = Ip;
+    Config->Ip4Info.RouteTable[0].SubnetMask     = Mask;
+    Config->Ip4Info.RouteTable[1].GatewayAddress = Gateway;
+  } else {
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+    goto ON_EXIT;
+  }
+
+  Config->NicAddr = Info->NicAddress;
+  Config->Perment = Perment;
+
+  Status = Info->NicIp4Config->SetInfo (Info->NicIp4Config, Config, TRUE);
+
+  if (EFI_ERROR (Status)) {
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_SET_FAIL), HiiHandle, Status);
+    goto ON_EXIT;
+  } 
+
+  Status = IfconfigStartIp4 (Info, Image);
+
+  if (EFI_ERROR (Status)) {
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_IP_CHILD_FAIL), HiiHandle, Status);
+  }
+  
+ON_EXIT:
+  if (Config != NULL) {
+    FreePool (Config);
+  }
+  
+  return Status;
+}
+
+
+VOID
+IfconfigShowNicInfo (
+  IN  CHAR16                   *Name
+  )
+/*++
+
+Routine Description:
+
+  Show the address information for the nic specified.
+
+Arguments:
+
+  Name - Pointer to the string containg the nic's name, if NULL, all nics'
+         information is shown.
+
+Returns:
+
+  None.
+
+--*/
+{
+  EFI_LIST_ENTRY                *Entry;
+  NIC_INFO                      *NicInfo;
+  UINT32                        Index;
+  EFI_IP4_IPCONFIG_DATA         *Ip4Config;
+  EFI_IPv4_ADDRESS              Gateway;
+
+  EFI_LIST_FOR_EACH (Entry, &NicInfoList) {
+    NicInfo = _CR (Entry, NIC_INFO, Link);
+
+    if ((Name != NULL) && (StriCmp (Name, NicInfo->Name) != 0)) {
+      continue;
+    }
+
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_NIC_NAME), HiiHandle, NicInfo->Name);
+    PrintMac (L"  MAC        : ", &NicInfo->NicAddress.MacAddr);
+
+    if (NicInfo->ConfigInfo == NULL) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_NIC_NOT_CONFIGURED), HiiHandle);
+      continue;
+    } 
+
+    if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_DHCP) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), HiiHandle, L"DHCP");
+    } else if (NicInfo->ConfigInfo->Source == IP4_CONFIG_SOURCE_STATIC) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), HiiHandle, L"STATIC");
+    } else {
+       PrintToken (STRING_TOKEN (STR_IFCONFIG_CONFIG_SOURCE), HiiHandle, L"Unknown");
+    }
+
+    PrintToken (
+      STRING_TOKEN (STR_IFCONFIG_PERMENT_STATUS),
+      HiiHandle,
+      (NicInfo->ConfigInfo->Perment? L"TRUE":L"FALSE")
+      );
+
+    Print (L"\n");
+    
+    Ip4Config = &NicInfo->ConfigInfo->Ip4Info;
+
+    PrintIp (L"  IP address : ", &Ip4Config->StationAddress);
+    PrintIp (L"  Mask       : ", &Ip4Config->SubnetMask);
+
+    EFI_IP4_TO_U32 (Gateway) = 0;
+    
+    for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {
+      if ((EFI_IP4_TO_U32 (Ip4Config->RouteTable[Index].SubnetAddress) == 0) &&
+          (EFI_IP4_TO_U32 (Ip4Config->RouteTable[Index].SubnetMask) == 0)) {
+        Gateway = Ip4Config->RouteTable[Index].GatewayAddress;
+      }
+    }
+   
+    PrintIp (L"  Gateway    : ", &Gateway);
+
+    Print (L"\n");
+
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), HiiHandle, Ip4Config->RouteTableSize);
+
+    for (Index = 0; Index < Ip4Config->RouteTableSize; Index++) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), HiiHandle, Index);
+      PrintIp (L"      Subnet : ", &Ip4Config->RouteTable[Index].SubnetAddress);
+      PrintIp (L"      Netmask: ", &Ip4Config->RouteTable[Index].SubnetMask);
+      PrintIp (L"      Gateway: ", &Ip4Config->RouteTable[Index].GatewayAddress);
+      Print   (L"\n");
+    }
+  }
+
+  return ;
+}
+
+EFI_STATUS
+IfconfigClearNicAddr (
+  IN CHAR16                     *Name
+  )
+/*++
+
+Routine Description:
+
+  Clear address configuration for the nic specified.
+
+Arguments:
+
+  Name - Pointer to the string containg the nic's name, if NULL, all nics'
+         address configurations are cleared.
+
+Returns:
+
+  EFI_SUCCESS - The address configuration is cleared.
+  other       - Some error occurs.
+
+--*/
+{
+  EFI_LIST_ENTRY                *Entry;
+  NIC_INFO                      *Info;
+  EFI_STATUS                    Status;
+  
+  EFI_LIST_FOR_EACH (Entry, &NicInfoList) {
+    Info = _CR (Entry, NIC_INFO, Link);
+
+    if ((Name != NULL) && (StrCmp (Name, Info->Name) != 0)) {
+      continue;
+    }
+    
+    Status = Info->NicIp4Config->SetInfo (Info->NicIp4Config, NULL, TRUE);
+
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+  
+}
+
+EFI_STATUS
+EFIAPI
+EfiMain (
+  IN  EFI_HANDLE                ImageHandle,
+  IN  EFI_SYSTEM_TABLE          *SystemTable
+  )
+/*++
+
+Routine Description:
+
+  The main procedure.
+
+Arguments:
+
+  ImageHandle - The image handle of this application.
+  SystemTable - Pointer to the EFI system table.
+
+Returns:
+
+  EFI_SUCCESS - The command finishes successfully.
+  other       - Some error occurs.
+
+--*/
+{
+  EFI_STATUS                    Status;
+  CHAR16                        *Useful;
+  SHELL_ARG_LIST                *Item;
+  SHELL_VAR_CHECK_CODE          RetCode;
+  SHELL_VAR_CHECK_PACKAGE       ChkPck;
+  EFI_LIST_ENTRY                *Entry;
+  NIC_INFO                      *Info;
+
+  //
+  // We are now being installed as an internal command driver, initialize
+  // as an nshell app and run
+  //
+  EFI_SHELL_APP_INIT (ImageHandle, SystemTable);
+
+  //
+  // Register our string package to HII database.
+  //
+  EFI_SHELL_STR_INIT (HiiHandle, STRING_ARRAY_NAME, EfiIfConfigGuid);
+
+  InitializeListHead (&NicInfoList);
+  ZeroMem (&ChkPck, sizeof (SHELL_VAR_CHECK_PACKAGE));
+
+  Status = EFI_INVALID_PARAMETER;
+  LibFilterNullArgs ();
+  RetCode = LibCheckVariables (SI, IfConfigCheckList, &ChkPck, &Useful);
+  if (VarCheckOk != RetCode) {
+    switch (RetCode) {
+    case VarCheckConflict:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_FLAG_CONFLICT), HiiHandle, L"IfConfig", Useful);
+      break;
+
+    case VarCheckDuplicate:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_DUP_FLAG), HiiHandle, L"IfConfig", Useful);
+      break;
+
+    case VarCheckLackValue:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_LACK_ARG), HiiHandle, L"IfConfig", Useful);
+      break;
+
+    case VarCheckUnknown:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_UNKNOWN_FLAG), HiiHandle, L"IfConfig", Useful);
+      break;
+
+    default:
+      break;
+    }
+
+    goto Done;
+  }
+
+  if (LibCheckVarGetFlag (&ChkPck, L"-b") != NULL) {
+    if (ChkPck.FlagCount == 1) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+      goto Done;
+    }
+
+    EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);
+  }
+
+  if (LibCheckVarGetFlag (&ChkPck, L"-?") != NULL) {
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_HELP), HiiHandle);
+
+    Status = EFI_SUCCESS;
+    goto Done;
+  }
+
+  Status = IfconfigGetAllNicInfo ();
+  if (EFI_ERROR (Status)) {
+    PrintToken (STRING_TOKEN (STR_IFCONFIG_GET_NIC_FAIL), HiiHandle, Status);
+    goto Done;
+  }
+
+  Item = LibCheckVarGetFlag (&ChkPck, L"-l");
+  if (Item != NULL) {
+
+    if (ChkPck.ValueCount > 1) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+    }
+
+    //
+    // Show the configuration.
+    //
+    IfconfigShowNicInfo ((ChkPck.ValueCount != 0) ? ChkPck.VarList->VarStr : NULL);
+  }
+
+  Item = LibCheckVarGetFlag (&ChkPck, L"-s");
+  if (Item != NULL) {
+
+    //
+    // The correct command line arguments for setting address are:
+    // IfConfig -s eth0 DHCP [perment]
+    // IfConfig -s eth0 static ip netmask gateway [perment]
+    //
+    if ((ChkPck.ValueCount < 2) || (ChkPck.ValueCount > 6) || (ChkPck.ValueCount == 4)) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+      goto Done;
+    }
+
+    IfconfigSetNicAddr (ChkPck.ValueCount, ChkPck.VarList, ImageHandle);
+  }
+
+  Item = LibCheckVarGetFlag (&ChkPck, L"-c");
+  if (Item != NULL) {
+
+    if (ChkPck.ValueCount > 1) {
+      PrintToken (STRING_TOKEN (STR_IFCONFIG_PROMPT_HELP), HiiHandle);
+    }
+
+    IfconfigClearNicAddr ((ChkPck.ValueCount != 0) ? ChkPck.VarList->VarStr : NULL);
+  }
+
+Done:
+
+  LibCheckVarFreeVarList (&ChkPck);
+
+  while (!IsListEmpty (&NicInfoList)) {
+    Entry = NicInfoList.Flink;
+    Info  = _CR (Entry, NIC_INFO, Link);
+
+    RemoveEntryList (Entry);
+    FreePool (Info);
+  }
+
+  return Status;
+}
+
+EFI_BOOTSHELL_CODE(EFI_APPLICATION_ENTRY_POINT(EfiMain))
diff --git a/IfConfig/IfConfig.h b/IfConfig/IfConfig.h
new file mode 100644 (file)
index 0000000..625fb49
--- /dev/null
@@ -0,0 +1,60 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation                                                         
+All rights reserved. This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution. The full text of the license may be found at         
+http://opensource.org/licenses/bsd-license.php                                            
+                                                                                          
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+Module Name:
+
+  IfConfig.c
+  
+Abstract:
+
+  Shell command "IfConfig"
+
+--*/
+#ifndef _EFI_IFCONFIG_H_
+#define _EFI_IFCONFIG_H_
+
+#include "EfiShellLib.h"
+#include "ShellNetHelper.h"
+
+#include EFI_PROTOCOL_DEFINITION (NicIp4Config)
+#include EFI_PROTOCOL_DEFINITION (Arp)
+
+#define EFI_IFCONFIG_GUID \
+  { \
+    0xb2f9929a, 0x648c, 0x4a9d, 0xb9, 0x92, 0xb1, 0x26, 0xfa, 0x32, 0x65, 0x82 \
+  }
+
+#define SEC_TO_NS             10000000
+
+typedef struct {
+  EFI_LIST_ENTRY              Link;
+  
+  EFI_HANDLE                  Handle;
+  NIC_ADDR                    NicAddress;
+  UINT16                      Name[IP4_NIC_NAME_LENGTH];
+  
+  EFI_NIC_IP4_CONFIG_PROTOCOL *NicIp4Config;
+  EFI_IP4_CONFIG_PROTOCOL     *Ip4Config;
+
+  NIC_IP4_CONFIG_INFO         *ConfigInfo;
+} NIC_INFO;
+
+typedef struct {
+  EFI_IP_ADDRESS              DestIp;
+  EFI_MAC_ADDRESS             DestMac;
+  EFI_IP_ADDRESS              LocalIp;
+  EFI_MAC_ADDRESS             LocalMac;
+  UINT8                       MacLen;
+  EFI_EVENT                   OnResolved;
+  BOOLEAN                     Duplicate;
+} ARP_REQUEST;
+
+#endif
diff --git a/IfConfig/IfConfig.inf b/IfConfig/IfConfig.inf
new file mode 100644 (file)
index 0000000..4f9876a
--- /dev/null
@@ -0,0 +1,62 @@
+#/*++
+#
+# Copyright (c) 2006, Intel Corporation                                                         
+# All rights reserved. This program and the accompanying materials                          
+# are licensed and made available under the terms and conditions of the BSD License         
+# which accompanies this distribution. The full text of the license may be found at         
+# http://opensource.org/licenses/bsd-license.php                                            
+#                                                                                           
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+# 
+#  Module Name:
+#
+#    IfConfig.inf
+#
+#  Abstract:
+#
+#    Component description file for IfConfig module
+#
+#--*/
+
+[defines]
+BASE_NAME            = IfConfig
+FILE_GUID            = 6394CF3D-D3DC-4f69-926D-AF9FFE59F922
+COMPONENT_TYPE       = APPLICATION
+
+[sources.common]
+  ..\ShCommonStrings.uni
+  IfConfigStrings.uni
+  IfConfig.c
+  IfConfig.h
+  ShellNetHelper.c
+  ShellNetHelper.h
+  
+[includes.common]
+  ..\Inc
+  ..\Library
+  $(EDK_SOURCE)\Foundation\Efi
+  $(EDK_SOURCE)\Foundation
+  $(EDK_SOURCE)\Foundation\Efi\Include
+  $(EDK_SOURCE)\Foundation\Include
+  $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+  $(EDK_SOURCE)\Foundation\FrameWork
+  $(EDK_SOURCE)\Foundation\FrameWork\Include
+  $(EDK_SOURCE)\Foundation\Core\Dxe
+  $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+  $(DEST_DIR)\
+
+[libraries.common]
+  EfiShellLib
+  EdkProtocolLib
+  EfiProtocolLib
+  EdkGuidLib
+  EfiDriverLib
+
+[nmake.common]
+  C_PROJ_FLAGS = $(C_PROJ_FLAGS)
+  IMAGE_ENTRY_POINT=EfiMain
+  C_STD_FLAGS = $(C_STD_FLAGS) /DEFI_BOOTSHELL
+  C_STD_FLAGS = $(C_STD_FLAGS) /DSTRING_ARRAY_NAME=$(BASE_NAME)Strings 
+  C_STD_FLAGS = $(C_STD_FLAGS) /DSTRING_DEFINES_FILE=\"$(BASE_NAME)StrDefs.h\"
+
diff --git a/IfConfig/IfConfigStrings.uni b/IfConfig/IfConfigStrings.uni
new file mode 100644 (file)
index 0000000..627d5c8
Binary files /dev/null and b/IfConfig/IfConfigStrings.uni differ
diff --git a/IfConfig/ShellNetHelper.c b/IfConfig/ShellNetHelper.c
new file mode 100644 (file)
index 0000000..a097b0a
--- /dev/null
@@ -0,0 +1,168 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation                                                         
+All rights reserved. This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution. The full text of the license may be found at         
+http://opensource.org/licenses/bsd-license.php                                            
+                                                                                          
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+Module Name:
+
+  ShellNetHelper.c
+
+Abstract:
+
+--*/
+#include "EfiShellLib.h"
+#include "ShellNetHelper.h"
+
+IP4_ADDR 
+mIp4AllMasks[IP4_MASK_NUM] = {
+  0x00000000, 0x80000000, 0xC0000000, 0xE0000000,
+  0xF0000000, 0xF8000000, 0xFC000000, 0xFE000000,
+  
+  0xFF000000, 0xFF800000, 0xFFC00000, 0xFFE00000,
+  0xFFF00000, 0xFFF80000, 0xFFFC0000, 0xFFFE0000,
+
+  0xFFFF0000, 0xFFFF8000, 0xFFFFC000, 0xFFFFE000,
+  0xFFFFF000, 0xFFFFF800, 0xFFFFFC00, 0xFFFFFE00,
+  
+  0xFFFFFF00, 0xFFFFFF80, 0xFFFFFFC0, 0xFFFFFFE0,
+  0xFFFFFFF0, 0xFFFFFFF8, 0xFFFFFFFC, 0xFFFFFFFE,
+  0xFFFFFFFF,  
+};
+
+INTN
+ShellGetIpClass (
+  IN IP4_ADDR     Addr
+  )
+{
+  UINT8     ByteOne;
+
+  ByteOne = (UINT8)(Addr >> 24);
+
+  if ((ByteOne & 0x80) == 0) {      
+    return IP4_ADDR_CLASSA;
+
+  } else if ((ByteOne & 0xC0) == 0x80) {      
+    return IP4_ADDR_CLASSB;
+
+  } else if ((ByteOne & 0xE0) == 0xC0) {      
+    return IP4_ADDR_CLASSC;
+
+  } else if ((ByteOne & 0xF0) == 0xE0) {      
+    return IP4_ADDR_CLASSD;
+
+  }else {                 
+    return IP4_ADDR_CLASSE;
+
+  } 
+}
+
+//
+// Is this a valid unicast address? If NetMask is zero, use the 
+// IP address's class to get the default mask.
+//
+BOOLEAN
+ShellIp4IsUnicast (
+  IN IP4_ADDR           Ip, 
+  IN IP4_ADDR           NetMask
+  )
+{
+  INTN                  Class;
+  
+  Class = ShellGetIpClass (Ip);
+  
+  if ((Ip == 0) || (Class >= IP4_ADDR_CLASSD)) {
+    return FALSE;
+  }
+
+  if (NetMask == 0) {
+    NetMask = mIp4AllMasks[Class << 3];
+  }
+  
+  if (((Ip & ~NetMask) == ~NetMask) || ((Ip & ~NetMask) == 0)) {
+    return FALSE;
+  }
+  
+  return TRUE;
+}
+
+EFI_STATUS 
+ShellCreateServiceChild (
+  IN  EFI_HANDLE  ControllerHandle,
+  IN  EFI_HANDLE  ImageHandle,
+  IN  EFI_GUID    *ServiceBindingGuid,
+  OUT EFI_HANDLE  *ChildHandle
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_SERVICE_BINDING_PROTOCOL  *Service;
+
+  if ((ServiceBindingGuid == NULL) || (ChildHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  //
+  // Get the ServiceBinding Protocol
+  //
+  Status = BS->OpenProtocol (
+                 ControllerHandle,       
+                 ServiceBindingGuid, 
+                 (VOID **)&Service,
+                 ImageHandle,   
+                 ControllerHandle,   
+                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                 );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Create a child
+  //
+  Status = Service->CreateChild (Service, ChildHandle);
+  return Status;
+}
+
+EFI_STATUS 
+ShellDestroyServiceChild (
+  IN  EFI_HANDLE  ControllerHandle,
+  IN  EFI_HANDLE  ImageHandle,
+  IN  EFI_GUID    *ServiceBindingGuid,
+  IN  EFI_HANDLE  ChildHandle
+  )
+{
+  EFI_STATUS                    Status;
+  EFI_SERVICE_BINDING_PROTOCOL  *Service;
+
+  if (ServiceBindingGuid == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  //
+  // Get the ServiceBinding Protocol
+  //
+  Status = BS->OpenProtocol (
+                 ControllerHandle,       
+                 ServiceBindingGuid, 
+                 (VOID **)&Service,
+                 ImageHandle,   
+                 ControllerHandle,   
+                 EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                 );
+
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // destory the child
+  //
+  Status = Service->DestroyChild (Service, ChildHandle);
+  return Status;
+}
diff --git a/IfConfig/ShellNetHelper.h b/IfConfig/ShellNetHelper.h
new file mode 100644 (file)
index 0000000..9a33d3f
--- /dev/null
@@ -0,0 +1,89 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation                                                         
+All rights reserved. This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution. The full text of the license may be found at         
+http://opensource.org/licenses/bsd-license.php                                            
+                                                                                          
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+Module Name:
+
+  ShellNetHelper.h
+
+Abstract:
+
+--*/
+#ifndef _EFI_SHELL_NET_HELPER_H_
+#define _EFI_SHELL_NET_HELPER_H_
+
+#include EFI_PROTOCOL_DEFINITION (ServiceBinding)
+
+enum {
+  EFI_IP_PROTO_ICMP      = 0x01,
+
+  IP4_ADDR_CLASSA        = 1,
+  IP4_ADDR_CLASSB,
+  IP4_ADDR_CLASSC,
+  IP4_ADDR_CLASSD,
+  IP4_ADDR_CLASSE,
+
+  IP4_MASK_NUM           = 33,
+};
+
+//
+//Iterate through the doule linked list. NOT delete safe
+//
+#define EFI_LIST_FOR_EACH(Entry, ListHead)    \
+  for(Entry = (ListHead)->Flink; Entry != (ListHead); Entry = Entry->Flink)
+
+//
+//Iterate through the doule linked list. This is delete-safe.
+//Don't touch NextEntry
+//
+#define EFI_LIST_FOR_EACH_SAFE(Entry, NextEntry, ListHead)            \
+  for(Entry = (ListHead)->Flink, NextEntry = Entry->Flink;\
+      Entry != (ListHead); Entry = NextEntry, NextEntry = Entry->Flink)
+
+
+typedef UINT32 IP4_ADDR;
+
+#define NTOHL(x)   \
+  (UINT32)((((UINT32)(x) & 0xff) << 24)    | (((UINT32)(x) & 0xff00) << 8 ) | \
+           (((UINT32)(x) & 0xff0000) >> 8) | (((UINT32)(x) & 0xff000000) >> 24))
+
+#define IP4_EQUAL_MASK(Ip1, Ip2, NetMask) \
+          (((Ip1) & (NetMask)) == ((Ip2) & (NetMask)))
+
+#define EFI_IP4_TO_U32(EfiIpAddr)   (*(IP4_ADDR*)((EfiIpAddr).Addr))
+#define EFI_IP4_NTOHL(EfiIp)        (NTOHL (EFI_IP4_TO_U32 ((EfiIp))))
+
+#define SHELL_MEM_EQUAL(pMac1, pMac2, Len) \
+        (CompareMem((pMac1), (pMac2), Len) == 0)
+
+#define SHELL_IS_DIGIT(Ch)  (('0' <= (Ch)) && ((Ch) <= '9'))
+
+BOOLEAN
+ShellIp4IsUnicast (
+  IN IP4_ADDR           Ip, 
+  IN IP4_ADDR           NetMask
+  );
+
+EFI_STATUS 
+ShellCreateServiceChild (
+  IN  EFI_HANDLE  ControllerHandle,
+  IN  EFI_HANDLE  ImageHandle,
+  IN  EFI_GUID    *ServiceBindingGuid,
+  OUT EFI_HANDLE  *ChildHandle
+);
+
+EFI_STATUS 
+ShellDestroyServiceChild (
+  IN  EFI_HANDLE  ControllerHandle,
+  IN  EFI_HANDLE  ImageHandle,
+  IN  EFI_GUID    *ServiceBindingGuid,
+  IN  EFI_HANDLE  ChildHandle
+);
+#endif
index ee17a21..0f0a56c 100644 (file)
@@ -547,37 +547,63 @@ _DevPathExtendedAcpi (
   IN VOID                 *DevPath
   )
 {
-  ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi;
+  ACPI_EXTENDED_HID_DEVICE_PATH   *ExtendedAcpi;
+  //
   // Index for HID, UID and CID strings, 0 for non-exist
-  UINT16 HIDSTRIdx = 0;
-  UINT16 UIDSTRIdx = 0;
-  UINT16 CIDSTRIdx = 0;
-  UINT16 i, length, anchor;
-  CHAR8 *AsChar8Array;
+  //
+  UINT16                          HIDSTRIdx;
+  UINT16                          UIDSTRIdx;
+  UINT16                          CIDSTRIdx;
+  UINT16                          Index;
+  UINT16                          Length;
+  UINT16                          Anchor;
+  CHAR8                           *AsChar8Array;
 
   ASSERT (Str != NULL);
   ASSERT (DevPath != NULL);
 
+  HIDSTRIdx    = 0;
+  UIDSTRIdx    = 0;
+  CIDSTRIdx    = 0;
   ExtendedAcpi = DevPath;
-  length = DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);
-  ASSERT (length >= 19);
+  Length       = DevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) ExtendedAcpi);
+
+  ASSERT (Length >= 19);
   AsChar8Array = (CHAR8 *) ExtendedAcpi;
 
+  //
   // find HIDSTR
-  anchor = 16;
-  for (i = anchor; i < length && AsChar8Array[i]; i++) ;
-  if (i > anchor) HIDSTRIdx = anchor;
+  //
+  Anchor = 16;
+  for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
+    ;
+  }
+  if (Index > Anchor) {
+    HIDSTRIdx = Anchor;
+  }
+  //
   // find UIDSTR
-  anchor = i + 1;
-  for (i = anchor; i < length && AsChar8Array[i]; i++) ;
-  if (i > anchor) UIDSTRIdx = anchor;
+  //
+  Anchor = Index + 1;
+  for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
+    ;
+  }
+  if (Index > Anchor) {
+    UIDSTRIdx = Anchor;
+  }
+  //
   // find CIDSTR
-  anchor = i + 1;
-  for (i = anchor; i < length && AsChar8Array[i]; i++) ;
-  if (i > anchor) CIDSTRIdx = anchor;
+  //
+  Anchor = Index + 1;
+  for (Index = Anchor; Index < Length && AsChar8Array[Index]; Index++) {
+    ;
+  }
+  if (Index > Anchor) {
+    CIDSTRIdx = Anchor;
+  }
   
   CatPrint (Str, L"Acpi(");
-  if (HIDSTRIdx) {
+  if (HIDSTRIdx != 0) {
     CatPrint (Str, L"%a,", AsChar8Array + HIDSTRIdx);
   } else {
     if ((ExtendedAcpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
@@ -586,20 +612,20 @@ _DevPathExtendedAcpi (
       CatPrint (Str, L"%08x,", ExtendedAcpi->HID);
     }
   }
-  if (UIDSTRIdx) {
-    CatPrint (Str, L"%a,", AsChar8Array + UIDSTRIdx);
-  } else {
-    CatPrint (Str, L"%x,", ExtendedAcpi->UID);
-  }
-  if (CIDSTRIdx) {
-    CatPrint (Str, L"%a)", AsChar8Array + CIDSTRIdx);
+  if (CIDSTRIdx != 0) {
+    CatPrint (Str, L"%a,", AsChar8Array + CIDSTRIdx);
   } else {
     if ((ExtendedAcpi->CID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
-      CatPrint (Str, L"PNP%04x)", EISA_ID_TO_NUM (ExtendedAcpi->CID));
+      CatPrint (Str, L"PNP%04x,", EISA_ID_TO_NUM (ExtendedAcpi->CID));
     } else {
-      CatPrint (Str, L"%08x)", ExtendedAcpi->CID);
+      CatPrint (Str, L"%08x,", ExtendedAcpi->CID);
     }
   }
+  if (UIDSTRIdx != 0) {
+    CatPrint (Str, L"%a)", AsChar8Array + UIDSTRIdx);
+  } else {
+    CatPrint (Str, L"%x)", ExtendedAcpi->UID);
+  }
 }
 
 VOID
diff --git a/Ping/Ping.c b/Ping/Ping.c
new file mode 100644 (file)
index 0000000..a014dde
--- /dev/null
@@ -0,0 +1,1353 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation                                                         
+All rights reserved. This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution.  The full text of the license may be found at        
+http://opensource.org/licenses/bsd-license.php                                            
+                                                                                          
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+Module Name:
+
+  Ping.c
+
+Abstract:
+
+  Implementation of shell application Ping.
+
+--*/
+
+#include "EfiShellLib.h"
+#include "CpuFuncs.h"
+#include EFI_ARCH_PROTOCOL_DEFINITION (Cpu)
+#include EFI_PROTOCOL_DEFINITION (Ip4)
+#include "Ping.h"
+#include STRING_DEFINES_FILE
+extern UINT8 STRING_ARRAY_NAME[];
+
+EFI_HII_HANDLE  HiiHandle;
+
+EFI_GUID  EfiPingGuid = EFI_PING_GUID;
+SHELL_VAR_CHECK_ITEM  PingCheckList[] = {
+  {
+    L"-n",
+    0x1,
+    0x6,
+    FlagTypeNeedVar
+  },
+  {
+    L"-l",
+    0x2,
+    0x5,
+    FlagTypeNeedVar
+  },
+  {
+    L"-?",
+    0x4,
+    0x3,
+    FlagTypeSingle
+  },
+  {
+    NULL,
+    0,
+    0,
+    0
+  }
+};
+
+EFI_IPv4_ADDRESS  DestinationIp;
+EFI_LIST_ENTRY    IcmpTxTimeoutList;
+UINT16            Identifier;
+UINT32            RxCount;
+UINT64            Frequency;
+UINT32            RttSum;
+UINT32            RttMin;
+UINT32            RttMax;
+
+STATIC
+UINT64
+GetTimerValue (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Get the current timestamp.
+
+Arguments:
+
+  None.
+
+Returns:
+
+  The current timestamp.
+
+--*/
+{
+  return EfiReadTsc ();
+}
+
+STATIC
+EFI_STATUS
+GetFrequency (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Calculate the frequency.
+
+Arguments:
+
+  None.
+
+Returns:
+
+  EFI_SUCCESS - The frequency is calculated.
+  other       - Some error occurs.
+
+--*/
+{
+  EFI_STATUS             Status;
+  EFI_CPU_ARCH_PROTOCOL  *Cpu;
+  UINT64                 CurrentTick;
+  UINT64                 TimerPeriod;
+
+  //
+  // Locate the Cpu Arch Protocol.
+  //
+  Status = BS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, &Cpu);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);
+  if (EFI_ERROR (Status)) {
+    //
+    // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the
+    // TimerPeriod by ourselves.
+    //
+    TimerPeriod = 1000000;
+  }
+
+  //
+  // The TimerPeriod is in femtosecond (1 femtosecond is  1e-15 second), so 1e+12
+  // is divided by TimerPeriod to produce the Feq in tick/ms.
+  //
+  Frequency = DivU64x32 (1000000000000, (UINTN) TimerPeriod, NULL);
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+UINT32
+CalculateTime (
+  UINT64  StartTick,
+  UINT64  EndTick
+  )
+/*++
+
+Routine Description:
+
+  Caculate the time for the period from StartTick to EndTick, the result is 
+  in millisencod.
+
+Arguments:
+
+  StartTick - The value of the start tick.
+  EndTick   - The value of the end tick.
+
+Returns:
+
+  The result time period, in millisecond.
+
+--*/
+{
+  UINT32  ElapsedTime;
+
+  //
+  // ElapsedTime is in ms.
+  //
+  ElapsedTime = (UINT32) DivU64x32 (EndTick - StartTick, (UINTN) (Frequency), NULL);
+
+  return ElapsedTime;
+}
+
+STATIC
+EFI_STATUS
+ParseIpAddress (
+  IN     CHAR16            *IpStr,
+  IN OUT EFI_IPv4_ADDRESS  *IpAddress
+  )
+/*++
+
+Routine Description:
+
+  Parse the IPv4 address in the string pointed to by IpStr and save the result
+  in the IpAddress.
+
+Arguments:
+
+  IpStr     - Pointer to the string containing the IPv4 address.
+  IpAddress - Pointer to the storage for the parsed IPv4 address.
+
+Returns:
+
+  EFI_SUCCESS           - The IPv4 address string is parsed and the result
+                          is in IpAddress.
+  EFI_INVALID_PARAMETER - The IPv4 address the string represents is in a wrong format.
+
+--*/
+{
+  UINTN   Addr;
+  UINT32  Index;
+
+  for (Index = 0; Index < 4; Index++) {
+
+    Addr = 0;
+
+    for (; (*IpStr != L'.') && (*IpStr != L'\0'); IpStr++) {
+
+      if ((*IpStr < L'0') || (*IpStr > L'9')) {
+        return EFI_INVALID_PARAMETER;       
+      }
+
+      Addr = Addr * 10 + (*IpStr - L'0');
+    }
+
+    if (Addr > 255) {
+      return EFI_INVALID_PARAMETER;
+    }
+
+    IpAddress->Addr[Index] = (UINT8) Addr;
+
+    if (*IpStr == L'\0') {
+      break;
+    }
+
+    //
+    // Skip the dot '.'
+    //
+    IpStr++;
+  }
+
+  //
+  // All four digits of an IPv4 address are here and no charaters left?
+  //
+  if ((Index < 3) || (*IpStr != L'\0')) {
+
+    return EFI_INVALID_PARAMETER;
+  }
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+UINT16
+NetAddChecksum (
+  IN UINT16 ChecksumA,
+  IN UINT16 ChecksumB
+  )
+/*++
+
+Routine Description:
+
+  Add two checksums.
+
+Arguments:
+
+  Checksum1 - The first checksum to be added.
+  Checksum2 - The second checksum to be added.
+
+Returns:
+
+  The new checksum.
+
+--*/
+{
+  UINT32  Sum;
+
+  Sum = ChecksumA + ChecksumB;
+
+  //
+  // two UINT16 can only add up to a carry of 1.
+  //
+  if (Sum >> 16) {
+    Sum = (Sum & 0xffff) + 1;
+  }
+
+  return (UINT16) Sum;
+}
+
+UINT16
+NetChecksum (
+  IN UINT8   *Buffer,
+  IN UINT32  Length
+  )
+/*++
+
+Routine Description:
+
+  Calculate the internet checksum (see RFC 1071)
+
+Arguments:
+
+  Packet             - Buffer which contains the data to be checksummed
+  Length             - Length to be checksummed
+
+Returns:
+
+  Checksum           - Returns the 16 bit ones complement of 
+                       ones complement sum of 16 bit words
+
+--*/
+{
+  UINT32  Sum;
+  UINT8   Odd;
+  UINT16  *Packet;
+
+  Packet  = (UINT16 *) Buffer;
+
+  Sum     = 0;
+  Odd     = (UINT8) (Length & 1);
+  Length >>= 1;
+  while (Length--) {
+    Sum += *Packet++;
+  }
+
+  if (Odd) {
+    Sum += *(UINT8 *) Packet;
+  }
+
+  Sum = (Sum & 0xffff) + (Sum >> 16);
+
+  //
+  // in case above carried
+  //
+  Sum += Sum >> 16;
+
+  return (UINT16) Sum;
+}
+
+STATIC
+VOID
+EFIAPI
+IcmpEchoRequestSent (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+/*++
+
+Routine Description:
+
+  The callback function of the ICMP transmit event.
+
+Arguments:
+
+  Event   - The event this function is registerd to.
+  Context - The context data registerd to the event.
+
+Returns:
+
+  None.
+
+--*/
+{
+}
+
+STATIC
+EFI_STATUS
+AddTxInfo (
+  IN UINT16  SeqNum,
+  IN UINT32  SentTime
+  )
+/*++
+
+Routine Description:
+
+  Add a ICMP_TX_INFO into the transmit timeout list.
+
+Arguments:
+
+  SeqNum   - The sequence number of the ICMP echo request.
+  SentTime - The time this ICMP echo request is sent.
+
+Returns:
+
+  EFI_SUCCESS          - The ICMP_TX_INFO is added into the transmit timeout list.
+  EFI_OUT_OF_RESOURCES - No available memory for the ICMP_TX_INFO.
+
+--*/
+{
+  ICMP_TX_INFO  *TxInfo;
+
+  TxInfo = (ICMP_TX_INFO *) AllocatePool (sizeof (ICMP_TX_INFO));
+  if (TxInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  InitializeListHead (&TxInfo->Link);
+  TxInfo->SeqNum   = SeqNum;
+  TxInfo->SentTime = SentTime;
+
+  InsertTailList (&IcmpTxTimeoutList, &TxInfo->Link);
+
+  return EFI_SUCCESS;
+}
+
+STATIC
+VOID
+RemoveTxInfo (
+  IN UINT16 SeqNum
+  )
+/*++
+
+Routine Description:
+
+  Remove a ICMP_TX_INFO from the transmit timeout list according to the SeqNum.
+
+Arguments:
+
+  SeqNum - The sequence number of the ICMP echo request.
+
+Returns:
+
+  None.
+
+--*/
+{
+  EFI_LIST_ENTRY  *Node;
+  ICMP_TX_INFO    *TxInfo;
+
+  for (Node = IcmpTxTimeoutList.Flink; Node != &IcmpTxTimeoutList; Node = Node->Flink) {
+
+    TxInfo = _CR (Node, ICMP_TX_INFO, Link);
+
+    if (TxInfo->SeqNum == SeqNum) {
+      RemoveEntryList (Node);
+      FreePool (TxInfo);
+      break;
+    }
+  }
+}
+
+STATIC
+VOID
+CheckTimeout (
+  IN UINT32  ElapsedSeconds
+  )
+/*++
+
+Routine Description:
+
+  Check the timeout of the transmitted ICMP echo request in the timeout list.
+
+Arguments:
+
+  ElapsedSeconds - The seconds elapsed since the first ICMP echo request is sent.
+
+Returns:
+
+  None.
+
+--*/
+{
+  EFI_LIST_ENTRY  *Node;
+  EFI_LIST_ENTRY  *NextNode;
+  ICMP_TX_INFO    *TxInfo;
+
+  for (Node = IcmpTxTimeoutList.Flink; Node != &IcmpTxTimeoutList; Node = NextNode) {
+
+    NextNode = Node->Flink;
+
+    TxInfo = _CR (Node, ICMP_TX_INFO, Link);
+
+    if (ElapsedSeconds - TxInfo->SentTime >= ICMP_DEFAULT_TIMEOUT) {
+      //
+      // Timeout, print the message.
+      //
+      PrintToken (STRING_TOKEN (STR_PING_TIMEOUT), HiiHandle);
+      RemoveEntryList (Node);
+      FreePool (TxInfo);
+    } else {
+      break;
+    }
+  }
+}
+
+STATIC
+VOID
+CleanTxTimeoutList (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Clean the timeout list.
+
+Arguments:
+
+  None.
+
+Returns:
+
+  None.
+
+--*/
+{
+  EFI_LIST_ENTRY  *Node;
+  ICMP_TX_INFO    *TxInfo;
+
+  while (!IsListEmpty (&IcmpTxTimeoutList)) {
+
+    Node   = IcmpTxTimeoutList.Flink;
+    TxInfo = _CR (Node, ICMP_TX_INFO, Link);
+
+    RemoveEntryList (Node);
+    FreePool (TxInfo);
+  }
+}
+
+STATIC
+VOID
+HandleIcmpEchoReply (
+  IN EFI_IP4_RECEIVE_DATA  *RxData
+  )
+/*++
+
+Routine Description:
+
+  Handle the received ICMP packet.
+
+Arguments:
+
+  RxData - Pointer to the EFI_IP4_RECEIVE_DATA passed up by Ip4 protocol.
+
+Returns:
+
+  None.
+
+--*/
+{
+  EFI_ICMP_ECHO_REPLY  *IcmpEchoReply;
+  UINT64               CurrentTick;
+  UINT32               Rtt;
+  CHAR16               Notation;
+
+  ASSERT (RxData != NULL);
+
+  if ((RxData->Header->Protocol != EFI_IP4_PROTO_ICMP) ||
+    (RxData->DataLength < sizeof (EFI_ICMP_ECHO_REPLY))) {
+    //
+    // Sanity checks.
+    //
+    return;
+  }
+
+  if (!EFI_IP4_EQUAL (RxData->Header->SourceAddress, DestinationIp)) {
+    //
+    // The source address of this ICMP packet is different from the DestinationIp.
+    //
+    return;
+  }
+
+  IcmpEchoReply = (EFI_ICMP_ECHO_REPLY *) RxData->FragmentTable[0].FragmentBuffer;
+
+  if ((IcmpEchoReply->Type != ICMP_TYPE_ECHO_REPLY) || (IcmpEchoReply->Code != 0)) {
+    //
+    // It's not an ICMP echo reply packet.
+    //
+    return;
+  }
+
+  if (IcmpEchoReply->Identifier != Identifier) {
+    //
+    // The Identifier differs.
+    //
+    return;
+  }
+
+  //
+  // Remove the TxInfo from the timeout list.
+  //
+  RemoveTxInfo (IcmpEchoReply->SeqNum);
+
+  RxCount++;
+
+  //
+  // Calculate the RTT.
+  //
+  CurrentTick = GetTimerValue ();
+  Rtt         = CalculateTime (IcmpEchoReply->TimerValue, CurrentTick);
+
+  RttSum += Rtt;
+
+  if (Rtt < RttMin) {
+    RttMin = Rtt;
+  }
+
+  if (Rtt > RttMax) {
+    RttMax = Rtt;
+  }
+
+  if (Rtt == 0) {
+    Notation = L'<';
+    Rtt = 1;
+  } else {
+    Notation = L'=';
+  }
+
+  //
+  // Print the message, such as RTT, TTL...
+  //
+  PrintToken (
+    STRING_TOKEN (STR_PING_REPLY_INFO),
+    HiiHandle,
+    RxData->Header->SourceAddress.Addr[0],
+    RxData->Header->SourceAddress.Addr[1],
+    RxData->Header->SourceAddress.Addr[2],
+    RxData->Header->SourceAddress.Addr[3],
+    RxData->DataLength - sizeof (EFI_ICMP_ECHO_REPLY) + sizeof (IcmpEchoReply->TimerValue),
+    Notation,
+    Rtt,
+    RxData->Header->TimeToLive
+    );
+}
+
+STATIC
+VOID
+EFIAPI
+IcmpEchoReplyRcvd (
+  IN EFI_EVENT  Event,
+  IN VOID       *Context
+  )
+/*++
+
+Routine Description:
+
+  The callback function of the ICMP receive event.
+
+Arguments:
+
+  Event   - The event this function is registered to.
+  Context - The context registered to this event.
+
+Returns:
+
+  None.
+
+--*/
+{
+}
+
+STATIC
+BOOLEAN
+AbortKey (
+  VOID
+  )
+/*++
+
+Routine Description:
+
+  Check whether there is abort key input from the keyboard.
+
+Arguments:
+
+  None
+
+Returns:
+
+  TRUE if some abort key is deteced, otherwise FALSE.
+
+--*/
+{
+  EFI_INPUT_KEY  Key;
+  EFI_STATUS     Status;
+
+  //
+  // Check for user intervention.
+  //
+  while (TRUE) {
+
+    Status = ST->ConIn->ReadKeyStroke (ST->ConIn, &Key);
+
+    if (EFI_ERROR (Status)) {
+      return FALSE;
+    }
+
+    switch (Key.UnicodeChar) {
+      case 0x1B:
+        //
+        // <Esc>
+        //
+      case 0x03:
+        //
+        // <Ctrl+C>
+        //
+        return TRUE;
+
+      case 0:
+        if (Key.ScanCode == 0x17) {
+          return TRUE;
+        }
+
+      default:
+        break;
+    }
+  }
+}
+
+STATIC
+BOOLEAN
+GetMapping (
+  IN EFI_IP4_PROTOCOL  *Ip4
+  )
+/*++
+
+Routine Description:
+
+  Get available address configuration.
+
+Arguments:
+
+  Ip4 - Pointer to the Ip4 protocol.
+
+Returns:
+
+  TRUE if mapping is done, otherwise FALSE.
+
+--*/
+{
+  EFI_STATUS         Status;
+  EFI_EVENT          TimeoutEvent;
+  EFI_IP4_MODE_DATA  Ip4ModeData;
+  BOOLEAN            IsMapDone;
+
+  IsMapDone = FALSE;
+
+  Status = BS->CreateEvent (EFI_EVENT_TIMER, EFI_TPL_CALLBACK, NULL, NULL, &TimeoutEvent);
+  if (EFI_ERROR (Status)) {
+    return IsMapDone;
+  }
+
+  //
+  // Start the timer, it will timeout after 5 seconds.
+  //
+  BS->SetTimer (TimeoutEvent, TimerRelative, 50000000);
+
+  while (EFI_ERROR (BS->CheckEvent (TimeoutEvent))) {
+
+    Ip4->Poll (Ip4);
+
+    Ip4->GetModeData (Ip4, &Ip4ModeData, NULL, NULL);
+
+    if (Ip4ModeData.IsConfigured) {
+
+      IsMapDone = TRUE;
+      break;
+    }
+  }
+
+  BS->CloseEvent (TimeoutEvent);
+
+  return IsMapDone;
+}
+
+STATIC
+EFI_STATUS
+OpenIp4Protocol (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_HANDLE        *ChildHandle,
+  OUT EFI_IP4_PROTOCOL  **Ip4Proto
+  )
+/*++
+
+Routine Description:
+
+  Create an Ip4 child and open the Ip4 protocol.
+
+Arguments:
+
+  ImageHandle - The image handle.
+  ChildHandle - Pointer to the child handle.
+  Ip4Proto    - Pointer to the Ip4 protocol.
+
+Returns:
+
+  EFI_SUCCESS - The ip4 protocol is opened.
+  other       - Some error occurs.
+
+--*/
+{
+  EFI_STATUS                    Status;
+  EFI_SERVICE_BINDING_PROTOCOL  *Ip4Sb;
+
+  Status = BS->LocateProtocol (&gEfiIp4ServiceBindingProtocolGuid, NULL, &Ip4Sb);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = Ip4Sb->CreateChild (Ip4Sb, ChildHandle);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = BS->OpenProtocol (
+                *ChildHandle,
+                &gEfiIp4ProtocolGuid,
+                (VOID **) Ip4Proto,
+                ImageHandle,
+                *ChildHandle,
+                EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                );
+  if (EFI_ERROR (Status)) {
+    Ip4Sb->DestroyChild (Ip4Sb, *ChildHandle);
+  }
+
+  return Status;
+}
+
+STATIC
+VOID
+CloseIp4Protocol (
+  IN EFI_HANDLE ImageHandle,
+  IN EFI_HANDLE ChildHandle
+  )
+/*++
+
+Routine Description:
+
+  Close the Ip4 protocol and destroy the Ip4 child.
+
+Arguments:
+
+  ImageHandle - The image handle.
+  ChildHandle - The child handle.
+
+Returns:
+
+  None.
+
+--*/
+{
+  EFI_SERVICE_BINDING_PROTOCOL  *Ip4Sb;
+
+  BS->CloseProtocol (
+        ChildHandle,
+        &gEfiIp4ProtocolGuid,
+        ImageHandle,
+        ChildHandle
+        );
+
+  BS->LocateProtocol (&gEfiIp4ServiceBindingProtocolGuid, NULL, &Ip4Sb);
+
+  Ip4Sb->DestroyChild (Ip4Sb, ChildHandle);
+}
+
+STATIC
+EFI_STATUS
+PingMainProc (
+  IN EFI_HANDLE  ImageHandle,
+  IN UINT32      SendNumber,
+  IN UINT32      BufferSize
+  )
+/*++
+
+Routine Description:
+
+  The main procedure of the Ping.
+
+Arguments:
+
+  ImageHandle - The image handle.
+  SendNumber  - The required counts of the ICMP echo request packets.
+  BufferSize  - The buffer size of the ICMP echo request packets.
+
+Returns:
+
+  EFI_SUCCESS - Ping successfully finished.
+  other       - Some error occurs.
+
+--*/
+{
+  EFI_STATUS                    Status;
+  EFI_IP4_PROTOCOL              *Ip4Proto;
+  EFI_HANDLE                    Ip4ChildHandle;
+  UINT64                        CurrentTick;
+  EFI_EVENT                     SendTimer;
+  EFI_IP4_COMPLETION_TOKEN      RxToken;
+  EFI_IP4_CONFIG_DATA           Ip4ConfigData;
+  EFI_IP4_COMPLETION_TOKEN      TxToken;
+  EFI_IP4_TRANSMIT_DATA         TxData;
+  UINT32                        TxBufferSize;
+  EFI_ICMP_ECHO_REQUEST         *IcmpEchoRequest;
+  UINT16                        HeadSum;
+  UINT16                        TempChecksum;
+  UINT32                        TxCount;
+  UINT32                        ElapsedSeconds;
+
+  //
+  // Initialize the variables.
+  //
+  InitializeListHead (&IcmpTxTimeoutList);
+  RxCount               = 0;
+  RttSum                = 0;
+  RttMin                = (UINT32) -1;
+  RttMax                = 0;
+  Ip4ChildHandle        = NULL;
+  SendTimer             = NULL;
+  TxToken.Event         = NULL;
+  RxToken.Event         = NULL;
+  RxToken.Packet.RxData = NULL;
+  IcmpEchoRequest       = NULL;
+  ElapsedSeconds        = 0;
+
+  Status = GetFrequency ();
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Open the Ip4 protocol.
+  //
+  Status = OpenIp4Protocol (ImageHandle, &Ip4ChildHandle, &Ip4Proto);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Set the configuration data.
+  //
+  Ip4ConfigData.DefaultProtocol   = EFI_IP4_PROTO_ICMP;
+  Ip4ConfigData.AcceptAnyProtocol = FALSE;
+  Ip4ConfigData.AcceptBroadcast   = FALSE;
+  Ip4ConfigData.AcceptIcmpErrors  = TRUE;
+  Ip4ConfigData.AcceptPromiscuous = FALSE;
+  Ip4ConfigData.DoNotFragment     = FALSE;
+  Ip4ConfigData.RawData           = FALSE;
+  Ip4ConfigData.ReceiveTimeout    = 0;
+  Ip4ConfigData.TransmitTimeout   = 0;
+  Ip4ConfigData.UseDefaultAddress = TRUE;
+  Ip4ConfigData.TimeToLive        = 128;
+  Ip4ConfigData.TypeOfService     = 0;
+
+  //
+  // Configure the Ip4 protocol.
+  //
+  Status = Ip4Proto->Configure (Ip4Proto, &Ip4ConfigData);
+  if (EFI_ERROR (Status) && (Status != EFI_NO_MAPPING)) {
+    PrintToken (STRING_TOKEN (STR_PING_CONFIG_IP4), HiiHandle, Status);
+    goto Exit;
+  }
+
+  if ((Status == EFI_NO_MAPPING) && !GetMapping (Ip4Proto)) {
+    //
+    // No available default address information.
+    //
+    PrintToken (STRING_TOKEN (STR_PING_MAPPING), HiiHandle);
+    goto Exit;
+  }
+
+  PrintToken (
+    STRING_TOKEN (STR_PING_START),
+    HiiHandle,
+    DestinationIp.Addr[0],
+    DestinationIp.Addr[1],
+    DestinationIp.Addr[2],
+    DestinationIp.Addr[3],
+    BufferSize
+    );
+
+  //
+  // Create receive event
+  //
+  Status = BS->CreateEvent (
+                EFI_EVENT_NOTIFY_SIGNAL,
+                EFI_TPL_CALLBACK,
+                IcmpEchoReplyRcvd,
+                &RxToken,
+                &RxToken.Event
+                );
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  RxToken.Packet.RxData = NULL;
+  RxToken.Status        = EFI_NOT_READY;
+
+  //
+  // Randomize the identifier first.
+  //
+  CurrentTick = GetTimerValue ();
+  Identifier = (UINT16) ((((UINT32) CurrentTick) >> 8) + SendNumber);
+
+  //
+  // Issue the asynchronous receive request.
+  //
+  Status = Ip4Proto->Receive (Ip4Proto, &RxToken);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Create a timer.
+  //
+  Status = BS->CreateEvent (EFI_EVENT_TIMER, EFI_TPL_CALLBACK, NULL, NULL, &SendTimer);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Start the periodic timer, the interval is 1 second.
+  //
+  Status = BS->SetTimer (SendTimer, TimerPeriodic, 10000000);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  //
+  // Create the transmit event.
+  //
+  Status = BS->CreateEvent (
+                 EFI_EVENT_NOTIFY_SIGNAL,
+                 EFI_TPL_CALLBACK,
+                 IcmpEchoRequestSent,
+                 &TxToken,
+                 &TxToken.Event
+                 );
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  TxBufferSize    = sizeof (EFI_ICMP_ECHO_REQUEST) + BufferSize;
+  IcmpEchoRequest = (EFI_ICMP_ECHO_REQUEST *) AllocatePool (TxBufferSize);
+
+  IcmpEchoRequest->Type       = ICMP_TYPE_ECHO_REQUEST;
+  IcmpEchoRequest->Code       = 0;
+  IcmpEchoRequest->Checksum   = 0;
+  IcmpEchoRequest->Identifier = Identifier;
+  IcmpEchoRequest->SeqNum     = 0;
+  IcmpEchoRequest->TimerValue = 0;
+
+  HeadSum = NetChecksum ((UINT8 *) IcmpEchoRequest, TxBufferSize);
+
+  IcmpEchoRequest->TimerValue = GetTimerValue();
+
+  //
+  // Calculate the final checksum and set the Checksum field.
+  //
+  TempChecksum = NetChecksum ((UINT8 *) &IcmpEchoRequest->TimerValue, sizeof (UINT64));
+  IcmpEchoRequest->Checksum = ~NetAddChecksum (HeadSum, TempChecksum);
+
+  TxData.DestinationAddress   = DestinationIp;
+  TxData.OverrideData         = 0;
+  TxData.OptionsLength        = 0;
+  TxData.OptionsBuffer        = NULL;
+  TxData.TotalDataLength      = TxBufferSize;
+  TxData.FragmentCount        = 1;
+
+  TxData.FragmentTable[0].FragmentBuffer = (VOID *) IcmpEchoRequest;
+  TxData.FragmentTable[0].FragmentLength = TxBufferSize;
+
+  TxToken.Packet.TxData = &TxData;
+  TxToken.Status        = EFI_ABORTED;
+
+  //
+  // Send out the first ICMP echo packet.
+  //
+  Status = Ip4Proto->Transmit (Ip4Proto, &TxToken);
+  if (EFI_ERROR (Status)) {
+    goto Exit;
+  }
+
+  AddTxInfo (IcmpEchoRequest->SeqNum, ElapsedSeconds);
+
+  TxCount = 1;
+
+  while (!AbortKey ()) {
+    Ip4Proto->Poll (Ip4Proto);
+
+    if (BS->CheckEvent (SendTimer) == EFI_SUCCESS) {
+
+      ElapsedSeconds++;
+
+      if (TxCount < SendNumber) {
+
+        if (TxToken.Status != EFI_SUCCESS) {
+          //
+          // If the previous transmit is not finished, cancel it first.
+          //
+          Ip4Proto->Cancel (Ip4Proto, &TxToken);
+        }
+        
+        //
+        // Increase the sequence number and get current tick.
+        //
+        IcmpEchoRequest->SeqNum++;
+        IcmpEchoRequest->TimerValue = GetTimerValue ();
+
+        //
+        // Calculate the final checksum and update the checksum field.
+        //
+        TempChecksum = NetChecksum ((UINT8 *) &IcmpEchoRequest->TimerValue, sizeof (UINT64));
+        TempChecksum = NetAddChecksum (TempChecksum, IcmpEchoRequest->SeqNum);
+        IcmpEchoRequest->Checksum = ~NetAddChecksum (HeadSum, TempChecksum);
+
+        TxToken.Status = EFI_ABORTED;
+
+        //
+        // Transmit a new ICMP echo packet.
+        //
+        Status = Ip4Proto->Transmit (Ip4Proto, &TxToken);
+        if (EFI_ERROR (Status)) {
+          break;
+        }
+
+        AddTxInfo (IcmpEchoRequest->SeqNum, ElapsedSeconds);
+
+        TxCount++;
+      }
+
+      CheckTimeout (ElapsedSeconds);
+    }
+
+    if (RxToken.Status == EFI_SUCCESS) {
+      //
+      // An ICMP packet is received, process it.
+      //
+      HandleIcmpEchoReply (RxToken.Packet.RxData);
+
+      BS->SignalEvent (RxToken.Packet.RxData->RecycleSignal);
+
+      RxToken.Packet.RxData = NULL;
+      RxToken.Status        = EFI_ABORTED;
+
+      //
+      // Continue receive the ICMP echo reply packets.
+      //
+      Status = Ip4Proto->Receive (Ip4Proto, &RxToken);
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+    }
+
+    if ((RxCount >= SendNumber) || (ElapsedSeconds + 1 - TxCount >= ICMP_DEFAULT_TIMEOUT)) {
+      //
+      // All echo replies are received or time out occurs.
+      //
+      break;
+    }
+  }
+
+  BS->SetTimer (SendTimer, TimerCancel, 0);
+
+  PrintToken (
+    STRING_TOKEN (STR_PING_STAT_HEAD),
+    HiiHandle,
+    DestinationIp.Addr[0],
+    DestinationIp.Addr[1],
+    DestinationIp.Addr[2],
+    DestinationIp.Addr[3]
+    );
+
+  PrintToken (
+    STRING_TOKEN (STR_PING_STAT_DETAIL),
+    HiiHandle,
+    TxCount,
+    RxCount,
+    TxCount - RxCount,
+    (100 * (TxCount - RxCount)) / TxCount
+    );
+
+  if (RxCount != 0) {
+    PrintToken (STRING_TOKEN (STR_PING_RTT_HEAD), HiiHandle);
+    PrintToken (STRING_TOKEN (STR_PING_RTT_DETAIL), HiiHandle, RttMin, RttMax, RttSum / RxCount);
+  }
+    
+Exit:
+  
+  if (Ip4Proto != NULL) {
+    //
+    // Reset the Ip4 instance.
+    //
+    Ip4Proto->Configure (Ip4Proto, NULL);
+  }
+
+  //
+  // Clean the transmit timeout list.
+  //
+  CleanTxTimeoutList ();
+
+  if (RxToken.Packet.RxData != NULL) {
+    //
+    // Try to recycle the RxData if there is any.
+    //
+    BS->SignalEvent (RxToken.Packet.RxData->RecycleSignal);
+  }
+
+  if (RxToken.Event != NULL) {
+    BS->CloseEvent (RxToken.Event);
+  }
+
+  if (TxToken.Event != NULL) {
+    BS->CloseEvent (TxToken.Event);
+  }
+
+  if (SendTimer != NULL) {
+    BS->CloseEvent (SendTimer);
+  }
+
+  if (IcmpEchoRequest != NULL) {
+    FreePool (IcmpEchoRequest);
+  }
+
+  CloseIp4Protocol (ImageHandle, Ip4ChildHandle);
+
+  return Status;
+}
+
+EFI_BOOTSHELL_CODE (EFI_APPLICATION_ENTRY_POINT (EfiMain))
+
+EFI_STATUS
+EFIAPI
+EfiMain (
+  IN  EFI_HANDLE        ImageHandle,
+  IN  EFI_SYSTEM_TABLE  *SystemTable
+  )
+/*++
+
+Routine Description:
+
+  Common entry point.
+
+Arguments:
+
+  ImageHandle - The image handle. 
+  SystemTable - The system table.
+
+Returns:
+
+  EFI_SUCCESS           - The command completed successfully.
+  EFI_INVALID_PARAMETER - The command line arguments are invalid.
+
+--*/
+{
+  EFI_STATUS                    Status;
+  UINT64                        BufferSize;
+  UINT64                        SendNumber;
+  CHAR16                        *Useful;
+  SHELL_ARG_LIST                *Item;
+  SHELL_VAR_CHECK_CODE          RetCode;
+  SHELL_VAR_CHECK_PACKAGE       ChkPck;
+
+  //
+  // We are now being installed as an internal command driver, initialize
+  // as an nshell app and run
+  //
+  EFI_SHELL_APP_INIT (ImageHandle, SystemTable);
+
+  //
+  // Register our string package to HII database.
+  //
+  EFI_SHELL_STR_INIT (HiiHandle, STRING_ARRAY_NAME, EfiPingGuid);
+
+  ZeroMem (&ChkPck, sizeof (SHELL_VAR_CHECK_PACKAGE));
+
+  Status = EFI_INVALID_PARAMETER;
+  LibFilterNullArgs ();
+  RetCode = LibCheckVariables (SI, PingCheckList, &ChkPck, &Useful);
+  if (VarCheckOk != RetCode) {
+    switch (RetCode) {
+    case VarCheckConflict:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_FLAG_CONFLICT), HiiHandle, L"Ping", Useful);
+      break;
+
+    case VarCheckDuplicate:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_DUP_FLAG), HiiHandle, L"Ping", Useful);
+      break;
+
+    case VarCheckLackValue:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_LACK_ARG), HiiHandle, L"Ping", Useful);
+      break;
+
+    case VarCheckUnknown:
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_UNKNOWN_FLAG), HiiHandle, L"Ping", Useful);
+      break;
+
+    default:
+      break;
+    }
+
+    goto Done;
+  }
+
+  //
+  // Output help.
+  //
+  if (LibCheckVarGetFlag (&ChkPck, L"-?") != NULL) {
+    if (ChkPck.ValueCount > 0 ) {
+      PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_TOO_MANY), HiiHandle, L"Ping");
+    } else {
+      PrintToken (STRING_TOKEN (STR_PING_HELP), HiiHandle);
+    }
+    goto Done;
+  }
+
+  if (ChkPck.ValueCount != 1) {
+    //
+    // Only 1 value count is permitted, that is the TargetIp.
+    //
+    PrintToken (STRING_TOKEN (STR_SHELLENV_GNC_INVALID_ARG), HiiHandle, L"Ping", SI->Argv[0]);
+    goto Done;
+  }
+
+  SendNumber = 10;
+  BufferSize = 0;
+
+  Item = LibCheckVarGetFlag (&ChkPck, L"-n");
+  if (Item !=  NULL) {
+    SendNumber = StrToUInteger (Item->VarStr, &Status);
+    if (EFI_ERROR (Status)) {
+      PrintToken (STRING_TOKEN (STR_PING_INVALID_COUNT), HiiHandle, Item->VarStr);
+      Status = EFI_INVALID_PARAMETER;
+      goto Done;
+    }
+  }
+
+  Item = LibCheckVarGetFlag (&ChkPck, L"-l");
+  if (Item != NULL) {
+    BufferSize = StrToUInteger (Item->VarStr, &Status);
+    if (EFI_ERROR (Status)) {
+      PrintToken (STRING_TOKEN (STR_PING_INVALID_BUFFER_SIZE), HiiHandle, Item->VarStr);
+      Status = EFI_INVALID_PARAMETER;
+      goto Done;
+    }
+
+    if (BufferSize > PING_MAX_BUFFER_SIZE) {
+      BufferSize = PING_MAX_BUFFER_SIZE;
+    }
+  }
+
+  Status = ParseIpAddress (ChkPck.VarList->VarStr, &DestinationIp);
+  if (EFI_ERROR (Status)) {
+    PrintToken (STRING_TOKEN (STR_PING_INVALID_IP), HiiHandle, ChkPck.VarList->VarStr);
+    goto Done;
+  }
+  
+  Status = PingMainProc (
+             ImageHandle,
+             (UINT32) SendNumber,
+             (UINT32) BufferSize
+             );
+
+Done:
+
+  LibCheckVarFreeVarList (&ChkPck);
+
+  return Status;
+}
diff --git a/Ping/Ping.h b/Ping/Ping.h
new file mode 100644 (file)
index 0000000..fddc8eb
--- /dev/null
@@ -0,0 +1,61 @@
+/*++
+
+Copyright (c) 2006, Intel Corporation                                                         
+All rights reserved. This program and the accompanying materials                          
+are licensed and made available under the terms and conditions of the BSD License         
+which accompanies this distribution. The full text of the license may be found at         
+http://opensource.org/licenses/bsd-license.php                                            
+                                                                                          
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+
+Module Name:
+
+  Ping.h
+
+Abstract:
+
+  declares interface functions
+
+Revision History
+
+--*/
+
+#ifndef _EFI_SHELL_PING_H_
+#define _EFI_SHELL_PING_H_
+#define EFI_PING_GUID \
+  { \
+    0x3047fb8f, 0xa669, 0x4acd, 0x9d, 0x6, 0x76, 0x36, 0x9e, 0x8c, 0xe4, 0xd4 \
+  }
+
+#define EFI_IP4_PROTO_ICMP      0x01
+
+#define ICMP_TYPE_ECHO_REQUEST  0x8
+#define ICMP_TYPE_ECHO_REPLY    0x0
+
+#define ICMP_DEFAULT_TIMEOUT    2
+
+#define PING_MAX_BUFFER_SIZE    32768
+
+#define EFI_IP4(IpAddr)         (*(UINT32 *) ((IpAddr).Addr))
+#define EFI_IP4_EQUAL(Ip1, Ip2) (EFI_IP4(Ip1) == EFI_IP4(Ip2))
+
+#pragma pack(1)
+typedef struct _EFI_ICMP_ECHO_REQUEST {
+  UINT8   Type;
+  UINT8   Code;
+  UINT16  Checksum;
+  UINT16  Identifier;
+  UINT16  SeqNum;
+  UINT64  TimerValue;
+} EFI_ICMP_ECHO_REQUEST, EFI_ICMP_ECHO_REPLY;
+#pragma pack()
+
+typedef struct _ICMP_TX_INFO {
+  EFI_LIST_ENTRY  Link;
+  UINT16          SeqNum;
+  UINT32          SentTime;
+} ICMP_TX_INFO;
+
+#endif
diff --git a/Ping/Ping.inf b/Ping/Ping.inf
new file mode 100644 (file)
index 0000000..fdd607b
--- /dev/null
@@ -0,0 +1,72 @@
+#/*++
+#
+# Copyright (c) 2006, Intel Corporation                                                         
+# All rights reserved. This program and the accompanying materials                          
+# are licensed and made available under the terms and conditions of the BSD License         
+# which accompanies this distribution. The full text of the license may be found at         
+# http://opensource.org/licenses/bsd-license.php                                            
+#                                                                                           
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
+# 
+#  Module Name:
+#
+#    Ping.inf
+#
+#  Abstract:
+#
+#    Component description file for ping application.
+#
+#--*/
+
+[defines]
+BASE_NAME            = Ping
+FILE_GUID            = FAAA94BA-7095-4c0f-8D69-8E00C8328863
+COMPONENT_TYPE       = APPLICATION
+
+[sources.common]
+  ..\ShCommonStrings.uni
+  PingStrings.uni
+  Ping.h
+  Ping.c
+
+[includes.common]
+  ..\Inc
+  ..\Library
+  $(EDK_SOURCE)\Foundation\Efi
+  $(EDK_SOURCE)\Foundation
+  $(EDK_SOURCE)\Foundation\Efi\Include
+  $(EDK_SOURCE)\Foundation\Include
+  $(EDK_SOURCE)\Foundation\Include\IndustryStandard
+  $(EDK_SOURCE)\Foundation\FrameWork
+  $(EDK_SOURCE)\Foundation\FrameWork\Include
+  $(EDK_SOURCE)\Foundation\Core\Dxe
+  $(EDK_SOURCE)\Foundation\Library\Dxe\Include
+  $(DEST_DIR)\
+
+[libraries.common]  
+  EfiShellLib
+  EdkProtocolLib
+  EdkFrameworkProtocolLib
+  EfiProtocolLib
+  ArchProtocolLib
+  EdkGuidLib
+  EdkFrameworkGuidLib
+  EfiDriverLib
+
+[libraries.Ia32]
+  CpuIA32Lib
+
+[libraries.Ipf]
+  CpuIA64Lib
+
+[Libraries.X64]
+  CpuIA32Lib
+
+[nmake.common]
+  C_PROJ_FLAGS = $(C_PROJ_FLAGS)
+  IMAGE_ENTRY_POINT=EfiMain
+  C_STD_FLAGS = $(C_STD_FLAGS) /DEFI_BOOTSHELL
+  C_STD_FLAGS = $(C_STD_FLAGS) /DSTRING_ARRAY_NAME=$(BASE_NAME)Strings 
+  C_STD_FLAGS = $(C_STD_FLAGS) /DSTRING_DEFINES_FILE=\"$(BASE_NAME)StrDefs.h\"
+
diff --git a/Ping/PingStrings.uni b/Ping/PingStrings.uni
new file mode 100644 (file)
index 0000000..d5df3ab
Binary files /dev/null and b/Ping/PingStrings.uni differ
index e2dfa06..5b4b442 100644 (file)
@@ -1,5 +1,5 @@
 /*++
-Copyright (c) 2005, Intel Corporation                                                         
+Copyright (c) 2005 - 2006, Intel Corporation                                                         
 All rights reserved. This program and the accompanying materials                          
 are licensed and made available under the terms and conditions of the BSD License         
 which accompanies this distribution. The full text of the license may be found at         
@@ -307,7 +307,6 @@ typedef struct {
   SMBIOS_STRING ManufactureDate;
   SMBIOS_STRING SerialNumber;
   SMBIOS_STRING DeviceName;
-  SMBIOS_STRING BankLocator;
   UINT8         DeviceChemistry;
   UINT16        DeviceCapacity;
   UINT16        DesignVoltage;
@@ -375,7 +374,7 @@ typedef struct {
   UINT16        Tolerance;
   UINT16        Accuracy;
   UINT32        OEMDefined;
-  UINT32        NominalValue;
+  UINT16        NominalValue;
 } SMBIOS_TYPE28;
 
 typedef struct {
@@ -476,7 +475,6 @@ typedef struct {
   SMBIOS_STRING AssetTagNumber;
   SMBIOS_STRING ModelPartNumber;
   SMBIOS_STRING RevisionLevel;
-  SMBIOS_STRING Description;
   UINT16        MaxPowerCapacity;
   UINT16        PowerSupplyCharacteristics;
   UINT16        InputVoltageProbeHandle;
index 8fca28b..3833f37 100644 (file)
@@ -651,7 +651,6 @@ Returns:
     PrintPendingString (pStruct, Type22, ManufactureDate);
     PrintPendingString (pStruct, Type22, SerialNumber);
     PrintPendingString (pStruct, Type22, DeviceName);
-    PrintPendingString (pStruct, Type22, BankLocator);
     DisplayPBDeviceChemistry (
       pStruct->Type22->DeviceChemistry,
       Option
@@ -841,7 +840,6 @@ Returns:
     PrintPendingString (pStruct, Type39, AssetTagNumber);
     PrintPendingString (pStruct, Type39, ModelPartNumber);
     PrintPendingString (pStruct, Type39, RevisionLevel);
-    PrintPendingString (pStruct, Type39, Description);
     PrintStructValueH (pStruct, Type39, MaxPowerCapacity);
     DisplaySPSCharacteristics (
       pStruct->Type39->PowerSupplyCharacteristics,
index ea339d2..734bbe7 100644 (file)
@@ -479,6 +479,7 @@ Returns:
     PrintToken (STRING_TOKEN (STR_COMP_NO_DIFFERENCE), HiiCompHandle);
   } else {
     PrintToken (STRING_TOKEN (STR_COMP_DIFFERENCE), HiiCompHandle);
+    Status = EFI_ABORTED;
   }
 
 Done:
index 337ac03..f90221c 100644 (file)
@@ -790,8 +790,7 @@ Returns:
 
 --*/
 {
-  CHAR16
-Var[3];
+  CHAR16 Var[3];
 
   ASSERT (NULL != Content);
   ASSERT (NULL != VarName);