aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib')
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c1441
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c1708
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c84
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h70
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf64
-rw-r--r--roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni176
6 files changed, 3543 insertions, 0 deletions
diff --git a/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
new file mode 100644
index 000000000..267217cf3
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
@@ -0,0 +1,1441 @@
+/** @file
+ The implementation for Shell command ifconfig based on IP4Config2 protocol.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiShellNetwork1CommandsLib.h"
+
+typedef enum {
+ IfConfigOpList = 1,
+ IfConfigOpSet = 2,
+ IfConfigOpClear = 3
+} IFCONFIG_OPCODE;
+
+typedef enum {
+ VarCheckReserved = -1,
+ VarCheckOk = 0,
+ VarCheckDuplicate,
+ VarCheckConflict,
+ VarCheckUnknown,
+ VarCheckLackValue,
+ VarCheckOutOfMem
+} VAR_CHECK_CODE;
+
+typedef enum {
+ FlagTypeSingle = 0,
+ FlagTypeNeedVar,
+ FlagTypeNeedSet,
+ FlagTypeSkipUnknown
+} VAR_CHECK_FLAG_TYPE;
+
+#define MACADDRMAXSIZE 32
+
+typedef struct _IFCONFIG_INTERFACE_CB {
+ EFI_HANDLE NicHandle;
+ LIST_ENTRY Link;
+ EFI_IP4_CONFIG2_PROTOCOL *IfCfg;
+ EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
+ EFI_IP4_CONFIG2_POLICY Policy;
+ UINT32 DnsCnt;
+ EFI_IPv4_ADDRESS DnsAddr[1];
+} IFCONFIG_INTERFACE_CB;
+
+typedef struct _ARG_LIST ARG_LIST;
+
+struct _ARG_LIST {
+ ARG_LIST *Next;
+ CHAR16 *Arg;
+};
+
+typedef struct _IFCONFIG4_PRIVATE_DATA {
+ LIST_ENTRY IfList;
+
+ UINT32 OpCode;
+ CHAR16 *IfName;
+ ARG_LIST *VarArg;
+} IFCONFIG_PRIVATE_DATA;
+
+typedef struct _VAR_CHECK_ITEM{
+ CHAR16 *FlagStr;
+ UINT32 FlagID;
+ UINT32 ConflictMask;
+ VAR_CHECK_FLAG_TYPE FlagType;
+} VAR_CHECK_ITEM;
+
+SHELL_PARAM_ITEM mIfConfigCheckList[] = {
+ {
+ L"-b",
+ TypeFlag
+ },
+ {
+ L"-l",
+ TypeValue
+ },
+ {
+ L"-r",
+ TypeValue
+ },
+ {
+ L"-c",
+ TypeValue
+ },
+ {
+ L"-s",
+ TypeMaxValue
+ },
+ {
+ NULL,
+ TypeMax
+ },
+};
+
+VAR_CHECK_ITEM mSetCheckList[] = {
+ {
+ L"static",
+ 0x00000001,
+ 0x00000001,
+ FlagTypeSingle
+ },
+ {
+ L"dhcp",
+ 0x00000002,
+ 0x00000001,
+ FlagTypeSingle
+ },
+ {
+ L"dns",
+ 0x00000008,
+ 0x00000004,
+ FlagTypeSingle
+ },
+ {
+ NULL,
+ 0x0,
+ 0x0,
+ FlagTypeSkipUnknown
+ },
+};
+
+STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";
+
+/**
+ Free the ARG_LIST.
+
+ @param List Pointer to ARG_LIST to free.
+**/
+VOID
+FreeArgList (
+ ARG_LIST *List
+)
+{
+ ARG_LIST *Next;
+ while (List->Next != NULL) {
+ Next = List->Next;
+ FreePool (List);
+ List = Next;
+ }
+
+ FreePool (List);
+}
+
+/**
+ Split a string with specified separator and save the substring to a list.
+
+ @param[in] String The pointer of the input string.
+ @param[in] Separator The specified separator.
+
+ @return The pointer of headnode of ARG_LIST.
+
+**/
+ARG_LIST *
+SplitStrToList (
+ IN CONST CHAR16 *String,
+ IN CHAR16 Separator
+ )
+{
+ CHAR16 *Str;
+ CHAR16 *ArgStr;
+ ARG_LIST *ArgList;
+ ARG_LIST *ArgNode;
+
+ if (*String == L'\0') {
+ return NULL;
+ }
+
+ //
+ // Copy the CONST string to a local copy.
+ //
+ Str = AllocateCopyPool (StrSize (String), String);
+ if (Str == NULL) {
+ return NULL;
+ }
+ ArgStr = Str;
+
+ //
+ // init a node for the list head.
+ //
+ ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
+ if (ArgNode == NULL) {
+ return NULL;
+ }
+ ArgList = ArgNode;
+
+ //
+ // Split the local copy and save in the list node.
+ //
+ while (*Str != L'\0') {
+ if (*Str == Separator) {
+ *Str = L'\0';
+ ArgNode->Arg = ArgStr;
+ ArgStr = Str + 1;
+ ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
+ if (ArgNode->Next == NULL) {
+ //
+ // Free the local copy of string stored in the first node
+ //
+ FreePool (ArgList->Arg);
+ FreeArgList (ArgList);
+ return NULL;
+ }
+ ArgNode = ArgNode->Next;
+ }
+
+ Str++;
+ }
+
+ ArgNode->Arg = ArgStr;
+ ArgNode->Next = NULL;
+
+ return ArgList;
+}
+
+/**
+ Check the correctness of input Args with '-s' option.
+
+ @param[in] CheckList The pointer of VAR_CHECK_ITEM array.
+ @param[in] Name The pointer of input arg.
+ @param[in] Init The switch to execute the check.
+
+ @return VarCheckOk Valid parameter or Initialize check successfully.
+ @return VarCheckDuplicate Duplicated parameter happened.
+ @return VarCheckConflict Conflicted parameter happened
+ @return VarCheckUnknown Unknown parameter.
+
+**/
+VAR_CHECK_CODE
+IfConfigRetriveCheckListByName(
+ IN VAR_CHECK_ITEM *CheckList,
+ IN CHAR16 *Name,
+ IN BOOLEAN Init
+)
+{
+ STATIC UINT32 CheckDuplicate;
+ STATIC UINT32 CheckConflict;
+ VAR_CHECK_CODE RtCode;
+ UINT32 Index;
+ VAR_CHECK_ITEM Arg;
+
+ if (Init) {
+ CheckDuplicate = 0;
+ CheckConflict = 0;
+ return VarCheckOk;
+ }
+
+ RtCode = VarCheckOk;
+ Index = 0;
+ Arg = CheckList[Index];
+
+ //
+ // Check the Duplicated/Conflicted/Unknown input Args.
+ //
+ while (Arg.FlagStr != NULL) {
+ if (StrCmp (Arg.FlagStr, Name) == 0) {
+
+ if (CheckDuplicate & Arg.FlagID) {
+ RtCode = VarCheckDuplicate;
+ break;
+ }
+
+ if (CheckConflict & Arg.ConflictMask) {
+ RtCode = VarCheckConflict;
+ break;
+ }
+
+ CheckDuplicate |= Arg.FlagID;
+ CheckConflict |= Arg.ConflictMask;
+ break;
+ }
+
+ Arg = CheckList[++Index];
+ }
+
+ if (Arg.FlagStr == NULL) {
+ RtCode = VarCheckUnknown;
+ }
+
+ return RtCode;
+}
+
+/**
+ The notify function of create event when performing a manual config.
+
+ @param[in] Event The event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the event.
+
+**/
+VOID
+EFIAPI
+IfConfigManualAddressNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ *((BOOLEAN *) Context) = TRUE;
+}
+
+/**
+ Print MAC address.
+
+ @param[in] Node The pointer of MAC address buffer.
+ @param[in] Size The size of MAC address buffer.
+
+**/
+VOID
+IfConfigPrintMacAddr (
+ IN UINT8 *Node,
+ IN UINT32 Size
+ )
+{
+ UINTN Index;
+
+ ASSERT (Size <= MACADDRMAXSIZE);
+
+ for (Index = 0; Index < Size; Index++) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_BODY), gShellNetwork1HiiHandle, Node[Index]);
+ if (Index + 1 < Size) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_COLON), gShellNetwork1HiiHandle);
+ }
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
+}
+
+
+/**
+ The get current status of all handles.
+
+ @param[in] IfName The pointer of IfName(interface name).
+ @param[in] IfList The pointer of IfList(interface list).
+
+ @retval EFI_SUCCESS The get status processed successfully.
+ @retval others The get status process failed.
+
+**/
+EFI_STATUS
+IfConfigGetInterfaceInfo (
+ IN CHAR16 *IfName,
+ IN LIST_ENTRY *IfList
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN HandleNum;
+ EFI_HANDLE *HandleBuffer;
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
+ EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ UINTN DataSize;
+
+ HandleBuffer = NULL;
+ HandleNum = 0;
+
+ IfInfo = NULL;
+ IfCb = NULL;
+
+ //
+ // Locate all the handles with ip4 service binding protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiIp4ServiceBindingProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) || (HandleNum == 0)) {
+ return Status;
+ }
+
+ //
+ // Enumerate all handles that installed with ip4 service binding protocol.
+ //
+ for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
+ IfCb = NULL;
+ IfInfo = NULL;
+ DataSize = 0;
+
+ //
+ // Ip4config protocol and ip4 service binding protocol are installed
+ // on the same handle.
+ //
+ ASSERT (HandleBuffer != NULL);
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiIp4Config2ProtocolGuid,
+ (VOID **) &Ip4Cfg2
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the interface information size.
+ //
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeInterfaceInfo,
+ &DataSize,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ goto ON_ERROR;
+ }
+
+ IfInfo = AllocateZeroPool (DataSize);
+
+ if (IfInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the interface info.
+ //
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeInterfaceInfo,
+ &DataSize,
+ IfInfo
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Check the interface name if required.
+ //
+ if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
+ FreePool (IfInfo);
+ continue;
+ }
+
+ DataSize = 0;
+
+ //
+ // Get the size of dns server list.
+ //
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeDnsServer,
+ &DataSize,
+ NULL
+ );
+
+ if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
+ goto ON_ERROR;
+ }
+
+ IfCb = AllocateZeroPool (sizeof (IFCONFIG_INTERFACE_CB) + DataSize);
+
+ if (IfCb == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ IfCb->NicHandle = HandleBuffer[HandleIndex];
+ IfCb->IfInfo = IfInfo;
+ IfCb->IfCfg = Ip4Cfg2;
+ IfCb->DnsCnt = (UINT32) (DataSize / sizeof (EFI_IPv4_ADDRESS));
+
+ //
+ // Get the dns server list if has.
+ //
+ if (DataSize > 0) {
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeDnsServer,
+ &DataSize,
+ IfCb->DnsAddr
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ }
+
+ //
+ // Get the config policy.
+ //
+ DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypePolicy,
+ &DataSize,
+ &IfCb->Policy
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ InsertTailList (IfList, &IfCb->Link);
+
+ if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
+ //
+ // Only need the appointed interface, keep the allocated buffer.
+ //
+ IfCb = NULL;
+ IfInfo = NULL;
+ break;
+ }
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ if (IfInfo != NULL) {
+ FreePool (IfInfo);
+ }
+
+ if (IfCb != NULL) {
+ FreePool (IfCb);
+ }
+
+ return Status;
+}
+
+/**
+ The list process of the ifconfig command.
+
+ @param[in] IfList The pointer of IfList(interface list).
+
+ @retval SHELL_SUCCESS The ifconfig command list processed successfully.
+ @retval others The ifconfig command list process failed.
+
+**/
+SHELL_STATUS
+IfConfigShowInterfaceInfo (
+ IN LIST_ENTRY *IfList
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ EFI_STATUS MediaStatus;
+ EFI_IPv4_ADDRESS Gateway;
+ UINT32 Index;
+
+ MediaStatus = EFI_SUCCESS;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
+ }
+
+ //
+ // Go through the interface list.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
+ IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
+
+ //
+ // Print interface name.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IF_NAME), gShellNetwork1HiiHandle, IfCb->IfInfo->Name);
+
+ //
+ // Get Media State.
+ //
+ if (EFI_SUCCESS == NetLibDetectMediaWaitTimeout (IfCb->NicHandle, 0, &MediaStatus)) {
+ if (MediaStatus != EFI_SUCCESS) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media disconnected");
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media present");
+ }
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media state unknown");
+ }
+
+ //
+ // Print interface config policy.
+ //
+ if (IfCb->Policy == Ip4Config2PolicyDhcp) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_DHCP), gShellNetwork1HiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_MAN), gShellNetwork1HiiHandle);
+ }
+
+ //
+ // Print mac address of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_HEAD), gShellNetwork1HiiHandle);
+
+ IfConfigPrintMacAddr (
+ IfCb->IfInfo->HwAddress.Addr,
+ IfCb->IfInfo->HwAddressSize
+ );
+
+ //
+ // Print IPv4 address list of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_HEAD), gShellNetwork1HiiHandle);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[0],
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[1],
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[2],
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[3]
+ );
+
+ //
+ // Print subnet mask list of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_SUBNET_MASK_HEAD), gShellNetwork1HiiHandle);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[0],
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[1],
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[2],
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[3]
+ );
+
+ //
+ // Print default gateway of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_GATEWAY_HEAD), gShellNetwork1HiiHandle);
+
+ ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));
+
+ for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
+ if ((CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&
+ (CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetMask , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){
+ CopyMem (&Gateway, &IfCb->IfInfo->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
+ }
+ }
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN)Gateway.Addr[0],
+ (UINTN)Gateway.Addr[1],
+ (UINTN)Gateway.Addr[2],
+ (UINTN)Gateway.Addr[3]
+ );
+
+ //
+ // Print route table entry.
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, IfCb->IfInfo->RouteTableSize);
+
+ for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
+ gShellNetwork1HiiHandle,
+ L"Subnet ",
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[0],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[1],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[2],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[3]
+ );
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
+ gShellNetwork1HiiHandle,
+ L"Netmask",
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[0],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[1],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[2],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[3]
+ );
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
+ gShellNetwork1HiiHandle,
+ L"Gateway",
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[0],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[1],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[2],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[3]
+ );
+ }
+
+ //
+ // Print dns server addresses list of the interface if has.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_HEAD), gShellNetwork1HiiHandle);
+
+ for (Index = 0; Index < IfCb->DnsCnt; Index++) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN) IfCb->DnsAddr[Index].Addr[0],
+ (UINTN) IfCb->DnsAddr[Index].Addr[1],
+ (UINTN) IfCb->DnsAddr[Index].Addr[2],
+ (UINTN) IfCb->DnsAddr[Index].Addr[3]
+ );
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
+ }
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
+
+ return SHELL_SUCCESS;
+}
+
+/**
+ The clean process of the ifconfig command to clear interface info.
+
+ @param[in] IfList The pointer of IfList(interface list).
+ @param[in] IfName The pointer of interface name.
+
+ @retval SHELL_SUCCESS The ifconfig command clean processed successfully.
+ @retval others The ifconfig command clean process failed.
+
+**/
+SHELL_STATUS
+IfConfigClearInterfaceInfo (
+ IN LIST_ENTRY *IfList,
+ IN CHAR16 *IfName
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ EFI_IP4_CONFIG2_POLICY Policy;
+
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
+ }
+
+ //
+ // Go through the interface list.
+ // If the interface name is specified, DHCP DORA process will be
+ // triggered by the policy transition (static -> dhcp).
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
+ IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
+
+ if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) {
+ Policy = Ip4Config2PolicyStatic;
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+
+ Policy = Ip4Config2PolicyDhcp;
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+
+ return ShellStatus;
+}
+
+/**
+ The set process of the ifconfig command.
+
+ @param[in] IfList The pointer of IfList(interface list).
+ @param[in] VarArg The pointer of ARG_LIST(Args with "-s" option).
+
+ @retval SHELL_SUCCESS The ifconfig command set processed successfully.
+ @retval others The ifconfig command set process failed.
+
+**/
+SHELL_STATUS
+IfConfigSetInterfaceInfo (
+ IN LIST_ENTRY *IfList,
+ IN ARG_LIST *VarArg
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ VAR_CHECK_CODE CheckCode;
+ EFI_EVENT TimeOutEvt;
+ EFI_EVENT MappedEvt;
+ BOOLEAN IsAddressOk;
+
+ EFI_IP4_CONFIG2_POLICY Policy;
+ EFI_IP4_CONFIG2_MANUAL_ADDRESS ManualAddress;
+ UINTN DataSize;
+ EFI_IPv4_ADDRESS Gateway;
+ IP4_ADDR SubnetMask;
+ IP4_ADDR TempGateway;
+ EFI_IPv4_ADDRESS *Dns;
+ ARG_LIST *Tmp;
+ UINTN Index;
+
+ CONST CHAR16* TempString;
+
+ Dns = NULL;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
+ return SHELL_INVALID_PARAMETER;
+ }
+
+ //
+ // Make sure to set only one interface each time.
+ //
+ IfCb = NET_LIST_USER_STRUCT (IfList->ForwardLink, IFCONFIG_INTERFACE_CB, Link);
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // Initialize check list mechanism.
+ //
+ CheckCode = IfConfigRetriveCheckListByName(
+ NULL,
+ NULL,
+ TRUE
+ );
+
+ //
+ // Create events & timers for asynchronous settings.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &TimeOutEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ IfConfigManualAddressNotify,
+ &IsAddressOk,
+ &MappedEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Parse the setting variables.
+ //
+ while (VarArg != NULL) {
+ //
+ // Check invalid parameters (duplication & unknown & conflict).
+ //
+ CheckCode = IfConfigRetriveCheckListByName(
+ mSetCheckList,
+ VarArg->Arg,
+ FALSE
+ );
+
+ if (VarCheckOk != CheckCode) {
+ switch (CheckCode) {
+ case VarCheckDuplicate:
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_DUPLICATE_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
+ break;
+
+ case VarCheckConflict:
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_CONFLICT_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
+ break;
+
+ case VarCheckUnknown:
+ //
+ // To handle unsupported option.
+ //
+ TempString = PermanentString;
+ if (StringNoCaseCompare(&VarArg->Arg, &TempString) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle, PermanentString);
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle unknown option.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNKNOWN_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
+ break;
+
+ default:
+ break;
+ }
+
+ VarArg = VarArg->Next;
+ continue;
+ }
+
+ //
+ // Process valid variables.
+ //
+ if (StrCmp(VarArg->Arg, L"dhcp") == 0) {
+ //
+ // Set dhcp config policy
+ //
+ Policy = Ip4Config2PolicyDhcp;
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ VarArg= VarArg->Next;
+
+ } else if (StrCmp (VarArg->Arg, L"static") == 0) {
+ VarArg= VarArg->Next;
+ if (VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ ZeroMem (&ManualAddress, sizeof (ManualAddress));
+
+ //
+ // Get manual IP address.
+ //
+ Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.Address);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // Get subnetmask.
+ //
+ VarArg = VarArg->Next;
+ if (VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.SubnetMask);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // Get gateway.
+ //
+ VarArg = VarArg->Next;
+ if (VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = NetLibStrToIp4 (VarArg->Arg, &Gateway);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // Need to check the gateway validity before set Manual Address.
+ // In case we can set manual address but fail to configure Gateway.
+ //
+ CopyMem (&SubnetMask, &ManualAddress.SubnetMask, sizeof (IP4_ADDR));
+ CopyMem (&TempGateway, &Gateway, sizeof (IP4_ADDR));
+ SubnetMask = NTOHL (SubnetMask);
+ TempGateway = NTOHL (TempGateway);
+ if ((SubnetMask != 0) &&
+ (SubnetMask != 0xFFFFFFFFu) &&
+ !NetIp4IsUnicast (TempGateway, SubnetMask)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_GATEWAY), gShellNetwork1HiiHandle, VarArg->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // Set manual config policy.
+ //
+ Policy = Ip4Config2PolicyStatic;
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Set Manual Address.
+ //
+ IsAddressOk = FALSE;
+
+ Status = IfCb->IfCfg->RegisterDataNotify (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeManualAddress,
+ MappedEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeManualAddress,
+ DataSize,
+ &ManualAddress
+ );
+
+ if (Status == EFI_NOT_READY) {
+ gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000);
+
+ while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
+ if (IsAddressOk) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+
+ IfCb->IfCfg->UnregisterDataNotify (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeManualAddress,
+ MappedEvt
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Set gateway.
+ //
+ DataSize = sizeof (EFI_IPv4_ADDRESS);
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeGateway,
+ DataSize,
+ &Gateway
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ VarArg = VarArg->Next;
+
+ } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
+ //
+ // Get DNS addresses.
+ //
+ VarArg = VarArg->Next;
+ Tmp = VarArg;
+ Index = 0;
+ while (Tmp != NULL) {
+ Index ++;
+ Tmp = Tmp->Next;
+ }
+
+ Dns = AllocatePool (Index * sizeof (EFI_IPv4_ADDRESS));
+ if (Dns == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Tmp = VarArg;
+ Index = 0;
+ while (Tmp != NULL) {
+ Status = NetLibStrToIp4 (Tmp->Arg, Dns + Index);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, Tmp->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ Index ++;
+ Tmp = Tmp->Next;
+ }
+
+ VarArg = Tmp;
+
+ //
+ // Set DNS addresses.
+ //
+ DataSize = Index * sizeof (EFI_IPv4_ADDRESS);
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeDnsServer,
+ DataSize,
+ Dns
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ }
+ }
+
+ON_EXIT:
+ if (Dns != NULL) {
+ FreePool (Dns);
+ }
+
+ return ShellStatus;
+
+}
+
+/**
+ The ifconfig command main process.
+
+ @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA.
+
+ @retval SHELL_SUCCESS ifconfig command processed successfully.
+ @retval others The ifconfig command process failed.
+
+**/
+SHELL_STATUS
+IfConfig (
+ IN IFCONFIG_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // Get configure information of all interfaces.
+ //
+ Status = IfConfigGetInterfaceInfo (
+ Private->IfName,
+ &Private->IfList
+ );
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ goto ON_EXIT;
+ }
+
+ switch (Private->OpCode) {
+ case IfConfigOpList:
+ ShellStatus = IfConfigShowInterfaceInfo (&Private->IfList);
+ break;
+
+ case IfConfigOpClear:
+ ShellStatus = IfConfigClearInterfaceInfo (&Private->IfList, Private->IfName);
+ break;
+
+ case IfConfigOpSet:
+ ShellStatus = IfConfigSetInterfaceInfo (&Private->IfList, Private->VarArg);
+ break;
+
+ default:
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+
+ON_EXIT:
+ return ShellStatus;
+}
+
+/**
+ The ifconfig command cleanup process, free the allocated memory.
+
+ @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA.
+
+**/
+VOID
+IfConfigCleanup (
+ IN IFCONFIG_PRIVATE_DATA *Private
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ IFCONFIG_INTERFACE_CB *IfCb;
+
+ ASSERT (Private != NULL);
+
+ //
+ // Clean the list which save the set config Args.
+ //
+ if (Private->VarArg != NULL) {
+ FreeArgList (Private->VarArg);
+ }
+
+ if (Private->IfName != NULL) {
+ FreePool (Private->IfName);
+ }
+
+ //
+ // Clean the IFCONFIG_INTERFACE_CB list.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->IfList) {
+ IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
+
+ RemoveEntryList (&IfCb->Link);
+
+ if (IfCb->IfInfo != NULL) {
+
+ FreePool (IfCb->IfInfo);
+ }
+
+ FreePool (IfCb);
+ }
+
+ FreePool (Private);
+}
+
+/**
+ Function for 'ifconfig' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval EFI_SUCCESS ifconfig command processed successfully.
+ @retval others The ifconfig command process failed.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIfconfig (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ IFCONFIG_PRIVATE_DATA *Private;
+ LIST_ENTRY *ParamPackage;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *ValueStr;
+ ARG_LIST *ArgList;
+ CHAR16 *ProblemParam;
+ CHAR16 *Str;
+
+ Status = EFI_INVALID_PARAMETER;
+ Private = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = ShellCommandLineParseEx (mIfConfigCheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle unsupported option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle,L"-c");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle no option.
+ //
+ if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
+ !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_OPTION), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle conflict options.
+ //
+ if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Private = AllocateZeroPool (sizeof (IFCONFIG_PRIVATE_DATA));
+ if (Private == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ InitializeListHead (&Private->IfList);
+
+ //
+ // To get interface name for the list option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
+ Private->OpCode = IfConfigOpList;
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
+ if (ValueStr != NULL) {
+ Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
+ if (Str == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Private->IfName = Str;
+ }
+ }
+
+ //
+ // To get interface name for the clear option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
+ Private->OpCode = IfConfigOpClear;
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
+ if (ValueStr != NULL) {
+ Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
+ if (Str == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Private->IfName = Str;
+ }
+ }
+
+ //
+ // To get interface name and corresponding Args for the set option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
+ if (ValueStr == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_INTERFACE), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // To split the configuration into multi-section.
+ //
+ ArgList = SplitStrToList (ValueStr, L' ');
+ if (ArgList == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Private->OpCode = IfConfigOpSet;
+ Private->IfName = ArgList->Arg;
+
+ Private->VarArg = ArgList->Next;
+
+ if (Private->IfName == NULL || Private->VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+
+ //
+ // Main process of ifconfig.
+ //
+ ShellStatus = IfConfig (Private);
+
+ON_EXIT:
+
+ ShellCommandLineFreeVarList (ParamPackage);
+
+ if (Private != NULL) {
+ IfConfigCleanup (Private);
+ }
+
+ return ShellStatus;
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
new file mode 100644
index 000000000..a3fa32515
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
@@ -0,0 +1,1708 @@
+/** @file
+ The implementation for Ping shell command.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "UefiShellNetwork1CommandsLib.h"
+
+#define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))
+
+UINT64 mCurrentTick = 0;
+
+//
+// Function templates to match the IPv4 and IPv6 commands that we use.
+//
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_POLL)(
+ IN VOID *This
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_TRANSMIT)(
+ IN VOID *This,
+ IN VOID *Token
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_RECEIVE)(
+ IN VOID *This,
+ IN VOID *Token
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_CANCEL)(
+ IN VOID *This,
+ IN VOID *Token OPTIONAL
+ );
+
+///
+/// A set of pointers to either IPv6 or IPv4 functions.
+/// Unknown which one to the ping command.
+///
+typedef struct {
+ PING_IPX_TRANSMIT Transmit;
+ PING_IPX_RECEIVE Receive;
+ PING_IPX_CANCEL Cancel;
+ PING_IPX_POLL Poll;
+}PING_IPX_PROTOCOL;
+
+
+typedef union {
+ VOID *RxData;
+ VOID *TxData;
+} PING_PACKET;
+
+//
+// PING_IPX_COMPLETION_TOKEN
+// structures are used for both transmit and receive operations.
+// This version is IP-unaware.
+//
+typedef struct {
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+ PING_PACKET Packet;
+} PING_IPX_COMPLETION_TOKEN;
+
+#pragma pack(1)
+typedef struct _ICMPX_ECHO_REQUEST_REPLY {
+ UINT8 Type;
+ UINT8 Code;
+ UINT16 Checksum;
+ UINT16 Identifier;
+ UINT16 SequenceNum;
+ UINT32 TimeStamp;
+ UINT8 Data[1];
+} ICMPX_ECHO_REQUEST_REPLY;
+#pragma pack()
+
+typedef struct _PING_ICMP_TX_INFO {
+ LIST_ENTRY Link;
+ UINT16 SequenceNum;
+ UINT32 TimeStamp;
+ PING_IPX_COMPLETION_TOKEN *Token;
+} PING_ICMPX_TX_INFO;
+
+#define DEFAULT_TIMEOUT 5000
+#define MAX_SEND_NUMBER 10000
+#define MAX_BUFFER_SIZE 32768
+#define DEFAULT_TIMER_PERIOD 358049
+#define ONE_SECOND 10000000
+#define PING_IP_CHOICE_IP4 1
+#define PING_IP_CHOICE_IP6 2
+#define DEFAULT_SEND_COUNT 10
+#define DEFAULT_BUFFER_SIZE 16
+#define ICMP_V4_ECHO_REQUEST 0x8
+#define ICMP_V4_ECHO_REPLY 0x0
+#define STALL_1_MILLI_SECOND 1000
+
+#define PING_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'i', 'n', 'g')
+typedef struct _PING_PRIVATE_DATA {
+ UINT32 Signature;
+ EFI_HANDLE NicHandle;
+ EFI_HANDLE IpChildHandle;
+ EFI_EVENT Timer;
+
+ UINT32 TimerPeriod;
+ UINT32 RttTimerTick;
+ EFI_EVENT RttTimer;
+
+ EFI_STATUS Status;
+ LIST_ENTRY TxList;
+ UINT16 RxCount;
+ UINT16 TxCount;
+ UINT64 RttSum;
+ UINT64 RttMin;
+ UINT64 RttMax;
+ UINT32 SequenceNum;
+
+ UINT32 SendNum;
+ UINT32 BufferSize;
+ UINT32 IpChoice;
+
+ PING_IPX_PROTOCOL ProtocolPointers;
+ VOID *IpProtocol;
+ UINT8 SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )];
+ UINT8 DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )];
+ PING_IPX_COMPLETION_TOKEN RxToken;
+ UINT16 FailedCount;
+} PING_PRIVATE_DATA;
+
+/**
+ Calculate the internet checksum (see RFC 1071).
+
+ @param[in] Packet Buffer which contains the data to be checksummed.
+ @param[in] Length Length to be checksummed.
+
+ @retval Checksum Returns the 16 bit ones complement of
+ ones complement sum of 16 bit words
+**/
+UINT16
+NetChecksum (
+ IN UINT8 *Buffer,
+ IN UINT32 Length
+ )
+{
+ UINT32 Sum;
+ UINT8 Odd;
+ UINT16 *Packet;
+
+ Packet = (UINT16 *) Buffer;
+
+ Sum = 0;
+ Odd = (UINT8) (Length & 1);
+ Length >>= 1;
+ while ((Length--) != 0) {
+ Sum += *Packet++;
+ }
+
+ if (Odd != 0) {
+ Sum += *(UINT8 *) Packet;
+ }
+
+ Sum = (Sum & 0xffff) + (Sum >> 16);
+
+ //
+ // in case above carried
+ //
+ Sum += Sum >> 16;
+
+ return (UINT16) Sum;
+}
+
+/**
+ Reads and returns the current value of register.
+ In IA64, the register is the Interval Timer Vector (ITV).
+ In X86(IA32/X64), the register is the Time Stamp Counter (TSC)
+
+ @return The current value of the register.
+
+**/
+
+STATIC CONST SHELL_PARAM_ITEM PingParamList[] = {
+ {
+ L"-l",
+ TypeValue
+ },
+ {
+ L"-n",
+ TypeValue
+ },
+ {
+ L"-s",
+ TypeValue
+ },
+ {
+ L"-_s",
+ TypeValue
+ },
+ {
+ L"-_ip6",
+ TypeFlag
+ },
+ {
+ NULL,
+ TypeMax
+ },
+};
+
+//
+// Global Variables in Ping command.
+//
+STATIC CONST CHAR16 *mDstString;
+STATIC CONST CHAR16 *mSrcString;
+
+/**
+ RTT timer tick routine.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+RttTimerTickRoutine (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ UINT32 *RttTimerTick;
+
+ RttTimerTick = (UINT32*) Context;
+ (*RttTimerTick)++;
+}
+
+/**
+ Get the timer period of the system.
+
+ This function tries to get the system timer period by creating
+ an 1ms period timer.
+
+ @return System timer period in MS, or 0 if operation failed.
+
+**/
+UINT32
+GetTimerPeriod(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT32 RttTimerTick;
+ EFI_EVENT TimerEvent;
+ UINT32 StallCounter;
+ EFI_TPL OldTpl;
+
+ RttTimerTick = 0;
+ StallCounter = 0;
+
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ RttTimerTickRoutine,
+ &RttTimerTick,
+ &TimerEvent
+ );
+ if (EFI_ERROR (Status)) {
+ return 0;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+ Status = gBS->SetTimer (
+ TimerEvent,
+ TimerPeriodic,
+ TICKS_PER_MS
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (TimerEvent);
+ return 0;
+ }
+
+ while (RttTimerTick < 10) {
+ gBS->Stall (STALL_1_MILLI_SECOND);
+ ++StallCounter;
+ }
+
+ gBS->RestoreTPL (OldTpl);
+
+ gBS->SetTimer (TimerEvent, TimerCancel, 0);
+ gBS->CloseEvent (TimerEvent);
+
+ return StallCounter / RttTimerTick;
+}
+
+/**
+ Initialize the timer event for RTT (round trip time).
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS RTT timer is started.
+ @retval Others Failed to start the RTT timer.
+
+**/
+EFI_STATUS
+PingInitRttTimer (
+ PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+
+ Private->TimerPeriod = GetTimerPeriod ();
+ if (Private->TimerPeriod == 0) {
+ return EFI_ABORTED;
+ }
+
+ Private->RttTimerTick = 0;
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ RttTimerTickRoutine,
+ &Private->RttTimerTick,
+ &Private->RttTimer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gBS->SetTimer (
+ Private->RttTimer,
+ TimerPeriodic,
+ TICKS_PER_MS
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->CloseEvent (Private->RttTimer);
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Free RTT timer event resource.
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+
+**/
+VOID
+PingFreeRttTimer (
+ PING_PRIVATE_DATA *Private
+ )
+{
+ if (Private->RttTimer != NULL) {
+ gBS->SetTimer (Private->RttTimer, TimerCancel, 0);
+ gBS->CloseEvent (Private->RttTimer);
+ }
+}
+
+/**
+ Read the current time.
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+
+ @retval the current tick value.
+**/
+UINT32
+ReadTime (
+ PING_PRIVATE_DATA *Private
+ )
+{
+ return Private->RttTimerTick;
+}
+
+/**
+ Calculate a duration in ms.
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+ @param[in] Begin The start point of time.
+ @param[in] End The end point of time.
+
+ @return The duration in ms.
+ @retval 0 The parameters were not valid.
+**/
+UINT32
+CalculateTick (
+ PING_PRIVATE_DATA *Private,
+ IN UINT32 Begin,
+ IN UINT32 End
+ )
+{
+ if (End < Begin) {
+ return (0);
+ }
+
+ return (End - Begin) * Private->TimerPeriod;
+}
+
+/**
+ Destroy PING_ICMPX_TX_INFO, and recollect the memory.
+
+ @param[in] TxInfo The pointer to PING_ICMPX_TX_INFO.
+ @param[in] IpChoice Whether the token is IPv4 or IPv6
+**/
+VOID
+PingDestroyTxInfo (
+ IN PING_ICMPX_TX_INFO *TxInfo,
+ IN UINT32 IpChoice
+ )
+{
+ EFI_IP6_TRANSMIT_DATA *Ip6TxData;
+ EFI_IP4_TRANSMIT_DATA *Ip4TxData;
+ EFI_IP6_FRAGMENT_DATA *FragData;
+ UINTN Index;
+
+ if (TxInfo == NULL) {
+ return;
+ }
+
+ if (TxInfo->Token != NULL) {
+
+ if (TxInfo->Token->Event != NULL) {
+ gBS->CloseEvent (TxInfo->Token->Event);
+ }
+
+ if (TxInfo->Token->Packet.TxData != NULL) {
+ if (IpChoice == PING_IP_CHOICE_IP6) {
+ Ip6TxData = TxInfo->Token->Packet.TxData;
+
+ if (Ip6TxData->OverrideData != NULL) {
+ FreePool (Ip6TxData->OverrideData);
+ }
+
+ if (Ip6TxData->ExtHdrs != NULL) {
+ FreePool (Ip6TxData->ExtHdrs);
+ }
+
+ for (Index = 0; Index < Ip6TxData->FragmentCount; Index++) {
+ FragData = Ip6TxData->FragmentTable[Index].FragmentBuffer;
+ if (FragData != NULL) {
+ FreePool (FragData);
+ }
+ }
+ } else {
+ Ip4TxData = TxInfo->Token->Packet.TxData;
+
+ if (Ip4TxData->OverrideData != NULL) {
+ FreePool (Ip4TxData->OverrideData);
+ }
+
+ for (Index = 0; Index < Ip4TxData->FragmentCount; Index++) {
+ FragData = Ip4TxData->FragmentTable[Index].FragmentBuffer;
+ if (FragData != NULL) {
+ FreePool (FragData);
+ }
+ }
+ }
+ }
+
+ FreePool (TxInfo->Token);
+ }
+
+ FreePool (TxInfo);
+}
+
+/**
+ Match the request, and reply with SequenceNum/TimeStamp.
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+ @param[in] Packet The pointer to ICMPX_ECHO_REQUEST_REPLY.
+
+ @retval EFI_SUCCESS The match is successful.
+ @retval EFI_NOT_FOUND The reply can't be matched with any request.
+
+**/
+EFI_STATUS
+Ping6MatchEchoReply (
+ IN PING_PRIVATE_DATA *Private,
+ IN ICMPX_ECHO_REQUEST_REPLY *Packet
+ )
+{
+ PING_ICMPX_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);
+
+ if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) {
+ Private->RxCount++;
+ RemoveEntryList (&TxInfo->Link);
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ The original intention is to send a request.
+ Currently, the application retransmits an icmp6 echo request packet
+ per second in sendnumber times that is specified by the user.
+ Because nothing can be done here, all things move to the timer rountine.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6OnEchoRequestSent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+}
+
+/**
+ receive reply, match and print reply infomation.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to context.
+
+**/
+VOID
+EFIAPI
+Ping6OnEchoReplyReceived (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ PING_PRIVATE_DATA *Private;
+ ICMPX_ECHO_REQUEST_REPLY *Reply;
+ UINT32 PayLoad;
+ UINT32 Rtt;
+
+ Private = (PING_PRIVATE_DATA *) Context;
+
+ if (Private == NULL || Private->Status == EFI_ABORTED || Private->Signature != PING_PRIVATE_DATA_SIGNATURE) {
+ return;
+ }
+
+ if (Private->RxToken.Packet.RxData == NULL) {
+ return;
+ }
+
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Reply = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer;
+ PayLoad = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength;
+ if (((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->NextHeader != IP6_ICMP) {
+ goto ON_EXIT;
+ }
+ if (!IP6_IS_MULTICAST ((EFI_IPv6_ADDRESS*)&Private->DstAddress) &&
+ !EFI_IP6_EQUAL (&((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv6_ADDRESS*)&Private->DstAddress)) {
+ goto ON_EXIT;
+ }
+
+ if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) {
+ goto ON_EXIT;
+ }
+ } else {
+ Reply = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer;
+ PayLoad = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength;
+ if (!IP4_IS_MULTICAST (EFI_IP4(*(EFI_IPv4_ADDRESS*)Private->DstAddress)) &&
+ !EFI_IP4_EQUAL (&((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv4_ADDRESS*)&Private->DstAddress)) {
+ goto ON_EXIT;
+ }
+
+ if ((Reply->Type != ICMP_V4_ECHO_REPLY) || (Reply->Code != 0)) {
+ goto ON_EXIT;
+ }
+ }
+
+
+ if (PayLoad != Private->BufferSize) {
+ goto ON_EXIT;
+ }
+ //
+ // Check whether the reply matches the sent request before.
+ //
+ Status = Ping6MatchEchoReply (Private, Reply);
+ if (EFI_ERROR(Status)) {
+ goto ON_EXIT;
+ }
+ //
+ // Display statistics on this icmp6 echo reply packet.
+ //
+ Rtt = CalculateTick (Private, Reply->TimeStamp, ReadTime (Private));
+
+ Private->RttSum += Rtt;
+ Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin;
+ Private->RttMax = Private->RttMax < Rtt ? Rtt : Private->RttMax;
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING_REPLY_INFO),
+ gShellNetwork1HiiHandle,
+ PayLoad,
+ mDstString,
+ Reply->SequenceNum,
+ Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->HopLimit:0,
+ Rtt,
+ Rtt + Private->TimerPeriod
+ );
+
+ON_EXIT:
+
+ //
+ // Recycle the packet before reusing RxToken
+ //
+ 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);
+
+ if (Private->RxCount < Private->SendNum) {
+ //
+ // Continue to receive icmp echo reply packets.
+ //
+ Private->RxToken.Status = EFI_ABORTED;
+
+ Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status);
+ Private->Status = EFI_ABORTED;
+ }
+ } else {
+ //
+ // All reply have already been received from the dest host.
+ //
+ Private->Status = EFI_SUCCESS;
+ }
+}
+
+/**
+ Create a PING_IPX_COMPLETION_TOKEN.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+ @param[in] TimeStamp The TimeStamp of request.
+ @param[in] SequenceNum The SequenceNum of request.
+
+ @return The pointer of PING_IPX_COMPLETION_TOKEN.
+
+**/
+PING_IPX_COMPLETION_TOKEN *
+PingGenerateToken (
+ IN PING_PRIVATE_DATA *Private,
+ IN UINT32 TimeStamp,
+ IN UINT16 SequenceNum
+ )
+{
+ EFI_STATUS Status;
+ PING_IPX_COMPLETION_TOKEN *Token;
+ VOID *TxData;
+ ICMPX_ECHO_REQUEST_REPLY *Request;
+ UINT16 HeadSum;
+ UINT16 TempChecksum;
+
+ Request = AllocateZeroPool (Private->BufferSize);
+ if (Request == NULL) {
+ return NULL;
+ }
+ TxData = AllocateZeroPool (Private->IpChoice==PING_IP_CHOICE_IP6?sizeof (EFI_IP6_TRANSMIT_DATA):sizeof (EFI_IP4_TRANSMIT_DATA));
+ if (TxData == NULL) {
+ FreePool (Request);
+ return NULL;
+ }
+ Token = AllocateZeroPool (sizeof (PING_IPX_COMPLETION_TOKEN));
+ if (Token == NULL) {
+ FreePool (Request);
+ FreePool (TxData);
+ return NULL;
+ }
+
+ //
+ // Assembly echo request packet.
+ //
+ Request->Type = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);
+ Request->Code = 0;
+ Request->SequenceNum = SequenceNum;
+ Request->Identifier = 0;
+ Request->Checksum = 0;
+
+ //
+ // Assembly token for transmit.
+ //
+ if (Private->IpChoice==PING_IP_CHOICE_IP6) {
+ Request->TimeStamp = TimeStamp;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength = 0;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs = NULL;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData = 0;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->DataLength = Private->BufferSize;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentCount = 1;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize;
+ } else {
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsLength = 0;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsBuffer = NULL;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->OverrideData = 0;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->TotalDataLength = Private->BufferSize;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentCount = 1;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[0] = Private->DstAddress[0];
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[1] = Private->DstAddress[1];
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[2] = Private->DstAddress[2];
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[3] = Private->DstAddress[3];
+
+ HeadSum = NetChecksum ((UINT8 *) Request, Private->BufferSize);
+ Request->TimeStamp = TimeStamp;
+ TempChecksum = NetChecksum ((UINT8 *) &Request->TimeStamp, sizeof (UINT64));
+ Request->Checksum = (UINT16)(~NetAddChecksum (HeadSum, TempChecksum));
+ }
+
+
+ Token->Status = EFI_ABORTED;
+ Token->Packet.TxData = TxData;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnEchoRequestSent,
+ Private,
+ &Token->Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Request);
+ FreePool (TxData);
+ FreePool (Token);
+ return NULL;
+ }
+
+ return Token;
+}
+
+/**
+ Transmit the PING_IPX_COMPLETION_TOKEN.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Transmitted successfully.
+ @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
+ @retval others Transmitted unsuccessfully.
+
+**/
+EFI_STATUS
+PingSendEchoRequest (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ PING_ICMPX_TX_INFO *TxInfo;
+
+ TxInfo = AllocateZeroPool (sizeof (PING_ICMPX_TX_INFO));
+
+ if (TxInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TxInfo->TimeStamp = ReadTime (Private);
+ TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);
+ TxInfo->Token = PingGenerateToken (
+ Private,
+ TxInfo->TimeStamp,
+ TxInfo->SequenceNum
+ );
+
+ if (TxInfo->Token == NULL) {
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ASSERT(Private->ProtocolPointers.Transmit != NULL);
+
+ InsertTailList (&Private->TxList, &TxInfo->Link);
+
+ Status = Private->ProtocolPointers.Transmit (Private->IpProtocol, TxInfo->Token);
+
+ if (EFI_ERROR (Status)) {
+ RemoveEntryList (&TxInfo->Link);
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ return Status;
+ }
+
+ Private->TxCount++;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Place a completion token into the receive packet queue to receive the echo reply.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Put the token into the receive packet queue successfully.
+ @retval others Put the token into the receive packet queue unsuccessfully.
+
+**/
+EFI_STATUS
+Ping6ReceiveEchoReply (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&Private->RxToken, sizeof (PING_IPX_COMPLETION_TOKEN));
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnEchoReplyReceived,
+ Private,
+ &Private->RxToken.Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Private->RxToken.Status = EFI_NOT_READY;
+
+ Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_RECEIVE), gShellNetwork1HiiHandle, Status);
+ }
+ return Status;
+}
+
+/**
+ Remove the timeout request from the list.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6OnTimerRoutine (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ PING_PRIVATE_DATA *Private;
+ PING_ICMPX_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ UINT64 Time;
+
+ Private = (PING_PRIVATE_DATA *) Context;
+ if (Private->Signature != PING_PRIVATE_DATA_SIGNATURE) {
+ Private->Status = EFI_NOT_FOUND;
+ return;
+ }
+
+ //
+ // Retransmit icmp6 echo request packets per second in sendnumber times.
+ //
+ if (Private->TxCount < Private->SendNum) {
+
+ Status = PingSendEchoRequest (Private);
+ if (Private->TxCount != 0){
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_SEND_REQUEST), gShellNetwork1HiiHandle, Private->TxCount + 1);
+ }
+ }
+ }
+ //
+ // Check whether any icmp6 echo request in the list timeout.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);
+ Time = CalculateTick (Private, TxInfo->TimeStamp, ReadTime (Private));
+
+ //
+ // Remove the timeout echo request from txlist.
+ //
+ if (Time > DEFAULT_TIMEOUT) {
+
+ if (EFI_ERROR (TxInfo->Token->Status)) {
+ Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token);
+ }
+ //
+ // Remove the timeout icmp6 echo request from list.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_TIMEOUT), gShellNetwork1HiiHandle, TxInfo->SequenceNum);
+
+ RemoveEntryList (&TxInfo->Link);
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+
+ Private->RxCount++;
+ Private->FailedCount++;
+
+ if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {
+ //
+ // All the left icmp6 echo request in the list timeout.
+ //
+ Private->Status = EFI_TIMEOUT;
+ }
+ }
+ }
+}
+
+/**
+ Determine if a IP4 address is Link Local.
+
+ 169.254.1.0 through 169.254.254.255 is link local.
+
+ @param[in] Address The address to test.
+
+ @retval TRUE It is.
+ @retval FALSE It is not.
+**/
+BOOLEAN
+PingNetIp4IsLinkLocalAddr (
+ IN CONST EFI_IPv4_ADDRESS *Address
+ )
+{
+ return ((BOOLEAN)(Address->Addr[0] == 169 && Address->Addr[1] == 254 && Address->Addr[2] >= 1 && Address->Addr[2] <= 254));
+}
+
+/**
+ Determine if a IP4 address is unspecified.
+
+ @param[in] Address The address to test.
+
+ @retval TRUE It is.
+ @retval FALSE It is not.
+**/
+BOOLEAN
+PingNetIp4IsUnspecifiedAddr (
+ IN CONST EFI_IPv4_ADDRESS *Address
+ )
+{
+ return ((BOOLEAN)((ReadUnaligned32 ((UINT32*)&Address->Addr[0])) == 0x00000000));
+}
+
+/**
+ Create a valid IP instance.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Create a valid IPx instance successfully.
+ @retval EFI_ABORTED Locate handle with ipx service binding protocol unsuccessfully.
+ @retval EFI_INVALID_PARAMETER The source address is unspecified when the destination address is a link-local address.
+ @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
+ @retval EFI_NOT_FOUND The source address is not found.
+**/
+EFI_STATUS
+PingCreateIpInstance (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN HandleNum;
+ EFI_HANDLE *HandleBuffer;
+ BOOLEAN UnspecifiedSrc;
+ EFI_STATUS MediaStatus;
+ EFI_SERVICE_BINDING_PROTOCOL *EfiSb;
+ VOID *IpXCfg;
+ EFI_IP6_CONFIG_DATA Ip6Config;
+ EFI_IP4_CONFIG_DATA Ip4Config;
+ VOID *IpXInterfaceInfo;
+ UINTN IfInfoSize;
+ EFI_IPv6_ADDRESS *Addr;
+ UINTN AddrIndex;
+
+ HandleBuffer = NULL;
+ UnspecifiedSrc = FALSE;
+ MediaStatus = EFI_SUCCESS;
+ EfiSb = NULL;
+ IpXInterfaceInfo = NULL;
+ IfInfoSize = 0;
+
+ //
+ // Locate all the handles with ip6 service binding protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {
+ return EFI_ABORTED;
+ }
+
+ if (Private->IpChoice == PING_IP_CHOICE_IP6 ? NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) : \
+ PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {
+ //
+ // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected.
+ //
+ UnspecifiedSrc = TRUE;
+ }
+
+ //
+ // Source address is required when pinging a link-local address.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_ERROR;
+ }
+ } else {
+ ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);
+ if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_ERROR;
+ }
+ }
+
+ //
+ // For each ip6 protocol, check interface addresses list.
+ //
+ for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
+ EfiSb = NULL;
+ IpXInterfaceInfo = NULL;
+ IfInfoSize = 0;
+
+ if (UnspecifiedSrc) {
+ //
+ // Check media.
+ //
+ NetLibDetectMediaWaitTimeout (HandleBuffer[HandleIndex], 0, &MediaStatus);
+ if (MediaStatus != EFI_SUCCESS) {
+ //
+ // Skip this one.
+ //
+ continue;
+ }
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
+ (VOID **) &EfiSb
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Ip6config protocol and ip6 service binding protocol are installed
+ // on the same handle.
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid,
+ (VOID **) &IpXCfg
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface information size.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ }
+
+ //
+ // Skip the ones not in current use.
+ //
+ if (Status == EFI_NOT_STARTED) {
+ continue;
+ }
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);
+
+ if (IpXInterfaceInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface info.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Check whether the source address is one of the interface addresses.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {
+ Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);
+
+ if (UnspecifiedSrc) {
+ if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {
+ //
+ // Select the interface automatically.
+ //
+ CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));
+ break;
+ }
+ } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
+ //
+ // Match a certain interface address.
+ //
+ break;
+ }
+ }
+
+ if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {
+ //
+ // Found a nic handle with right interface address.
+ //
+ break;
+ }
+ } else {
+ if (UnspecifiedSrc) {
+ if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) &&
+ !PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
+ //
+ // Select the interface automatically.
+ //
+ break;
+ }
+ } else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
+ //
+ // Match a certain interface address.
+ //
+ break;
+ }
+ }
+
+ FreePool (IpXInterfaceInfo);
+ IpXInterfaceInfo = NULL;
+ }
+ //
+ // No exact interface address matched.
+ //
+
+ if (HandleIndex == HandleNum) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIGD_NIC_NF), gShellNetwork1HiiHandle, L"ping");
+ Status = EFI_NOT_FOUND;
+ goto ON_ERROR;
+ }
+
+ Private->NicHandle = HandleBuffer[HandleIndex];
+
+ ASSERT (EfiSb != NULL);
+ Status = EfiSb->CreateChild (EfiSb, &Private->IpChildHandle);
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = gBS->OpenProtocol (
+ Private->IpChildHandle,
+ &gEfiIp6ProtocolGuid,
+ &Private->IpProtocol,
+ gImageHandle,
+ Private->IpChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+
+ ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA));
+
+ //
+ // Configure the ip6 instance for icmp6 packet exchange.
+ //
+ Ip6Config.DefaultProtocol = 58;
+ Ip6Config.AcceptAnyProtocol = FALSE;
+ Ip6Config.AcceptIcmpErrors = TRUE;
+ Ip6Config.AcceptPromiscuous = FALSE;
+ Ip6Config.TrafficClass = 0;
+ Ip6Config.HopLimit = 128;
+ Ip6Config.FlowLabel = 0;
+ Ip6Config.ReceiveTimeout = 0;
+ Ip6Config.TransmitTimeout = 0;
+
+ IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress);
+ IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress);
+
+ Status = ((EFI_IP6_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip6Config);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ Private->ProtocolPointers.Transmit = (PING_IPX_TRANSMIT )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Transmit;
+ Private->ProtocolPointers.Receive = (PING_IPX_RECEIVE )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Receive;
+ Private->ProtocolPointers.Cancel = (PING_IPX_CANCEL )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Cancel;
+ Private->ProtocolPointers.Poll = (PING_IPX_POLL )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Poll;
+ } else {
+ Status = gBS->OpenProtocol (
+ Private->IpChildHandle,
+ &gEfiIp4ProtocolGuid,
+ &Private->IpProtocol,
+ gImageHandle,
+ Private->IpChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+
+ ZeroMem (&Ip4Config, sizeof (EFI_IP4_CONFIG_DATA));
+
+ //
+ // Configure the ip4 instance for icmp4 packet exchange.
+ //
+ Ip4Config.DefaultProtocol = 1;
+ Ip4Config.AcceptAnyProtocol = FALSE;
+ Ip4Config.AcceptBroadcast = FALSE;
+ Ip4Config.AcceptIcmpErrors = TRUE;
+ Ip4Config.AcceptPromiscuous = FALSE;
+ Ip4Config.DoNotFragment = FALSE;
+ Ip4Config.RawData = FALSE;
+ Ip4Config.ReceiveTimeout = 0;
+ Ip4Config.TransmitTimeout = 0;
+ Ip4Config.UseDefaultAddress = TRUE;
+ Ip4Config.TimeToLive = 128;
+ Ip4Config.TypeOfService = 0;
+
+ Status = ((EFI_IP4_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip4Config);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ Private->ProtocolPointers.Transmit = (PING_IPX_TRANSMIT )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Transmit;
+ Private->ProtocolPointers.Receive = (PING_IPX_RECEIVE )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Receive;
+ Private->ProtocolPointers.Cancel = (PING_IPX_CANCEL )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Cancel;
+ Private->ProtocolPointers.Poll = (PING_IPX_POLL )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Poll;
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ if (IpXInterfaceInfo != NULL) {
+ FreePool (IpXInterfaceInfo);
+ }
+
+ if ((EfiSb != NULL) && (Private->IpChildHandle != NULL)) {
+ EfiSb->DestroyChild (EfiSb, Private->IpChildHandle);
+ }
+
+ return Status;
+}
+
+/**
+ Destroy the IP instance.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+**/
+VOID
+Ping6DestroyIp6Instance (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERVICE_BINDING_PROTOCOL *IpSb;
+
+ gBS->CloseProtocol (
+ Private->IpChildHandle,
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ProtocolGuid:&gEfiIp4ProtocolGuid,
+ gImageHandle,
+ Private->IpChildHandle
+ );
+
+ Status = gBS->HandleProtocol (
+ Private->NicHandle,
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
+ (VOID **) &IpSb
+ );
+
+ if (!EFI_ERROR(Status)) {
+ IpSb->DestroyChild (IpSb, Private->IpChildHandle);
+ }
+}
+
+
+/**
+ The Ping Process.
+
+ @param[in] SendNumber The send request count.
+ @param[in] BufferSize The send buffer size.
+ @param[in] SrcAddress The source address.
+ @param[in] DstAddress The destination address.
+ @param[in] IpChoice The choice between IPv4 and IPv6.
+
+ @retval SHELL_SUCCESS The ping processed successfullly.
+ @retval others The ping processed unsuccessfully.
+**/
+SHELL_STATUS
+ShellPing (
+ IN UINT32 SendNumber,
+ IN UINT32 BufferSize,
+ IN EFI_IPv6_ADDRESS *SrcAddress,
+ IN EFI_IPv6_ADDRESS *DstAddress,
+ IN UINT32 IpChoice
+ )
+{
+ EFI_STATUS Status;
+ PING_PRIVATE_DATA *Private;
+ PING_ICMPX_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+ Private = AllocateZeroPool (sizeof (PING_PRIVATE_DATA));
+
+ if (Private == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+
+ Private->IpChoice = IpChoice;
+ Private->Signature = PING_PRIVATE_DATA_SIGNATURE;
+ Private->SendNum = SendNumber;
+ Private->BufferSize = BufferSize;
+ Private->RttMin = ~((UINT64 )(0x0));
+ Private->Status = EFI_NOT_READY;
+
+ CopyMem(&Private->SrcAddress, SrcAddress, sizeof(Private->SrcAddress));
+ CopyMem(&Private->DstAddress, DstAddress, sizeof(Private->DstAddress));
+
+ InitializeListHead (&Private->TxList);
+
+ //
+ // Open and configure a ip instance for us.
+ //
+ Status = PingCreateIpInstance (Private);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Print the command line itself.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_START), gShellNetwork1HiiHandle, mDstString, Private->BufferSize);
+ //
+ // Create a ipv6 token to receive the first icmp6 echo reply packet.
+ //
+ Status = Ping6ReceiveEchoReply (Private);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Create and start timer to send icmp6 echo request packet per second.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnTimerRoutine,
+ Private,
+ &Private->Timer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Start a timer to calculate the RTT.
+ //
+ Status = PingInitRttTimer (Private);
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Create a ipv6 token to send the first icmp6 echo request packet.
+ //
+ Status = PingSendEchoRequest (Private);
+ //
+ // EFI_NOT_READY for IPsec is enable and IKE is not established.
+ //
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ if(Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOSOURCE_INDO), gShellNetwork1HiiHandle, mDstString);
+ } else if (Status == RETURN_NO_MAPPING) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, L"ping", Status);
+ }
+
+ goto ON_EXIT;
+ }
+
+ Status = gBS->SetTimer (
+ Private->Timer,
+ TimerPeriodic,
+ ONE_SECOND
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Control the ping6 process by two factors:
+ // 1. Hot key
+ // 2. Private->Status
+ // 2.1. success means all icmp6 echo request packets get reply packets.
+ // 2.2. timeout means the last icmp6 echo reply request timeout to get reply.
+ // 2.3. noready means ping6 process is on-the-go.
+ //
+ while (Private->Status == EFI_NOT_READY) {
+ Status = Private->ProtocolPointers.Poll (Private->IpProtocol);
+ if (ShellGetExecutionBreakFlag()) {
+ Private->Status = EFI_ABORTED;
+ goto ON_STAT;
+ }
+ }
+
+ON_STAT:
+ //
+ // Display the statistics in all.
+ //
+ gBS->SetTimer (Private->Timer, TimerCancel, 0);
+
+ if (Private->TxCount != 0) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING_STAT),
+ gShellNetwork1HiiHandle,
+ Private->TxCount,
+ (Private->RxCount - Private->FailedCount),
+ (100 - ((100 * (Private->RxCount - Private->FailedCount)) / Private->TxCount)),
+ Private->RttSum
+ );
+ }
+
+ if (Private->RxCount > Private->FailedCount) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING_RTT),
+ gShellNetwork1HiiHandle,
+ Private->RttMin,
+ Private->RttMin + Private->TimerPeriod,
+ Private->RttMax,
+ Private->RttMax + Private->TimerPeriod,
+ DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL),
+ DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL) + Private->TimerPeriod
+ );
+ }
+
+ON_EXIT:
+
+ if (Private != NULL) {
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);
+
+ if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) {
+ Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token);
+ }
+
+ RemoveEntryList (&TxInfo->Link);
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ }
+
+ PingFreeRttTimer (Private);
+
+ if (Private->Timer != NULL) {
+ gBS->CloseEvent (Private->Timer);
+ }
+
+ if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) {
+ Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, &Private->RxToken);
+ }
+
+ if (Private->RxToken.Event != NULL) {
+ gBS->CloseEvent (Private->RxToken.Event);
+ }
+
+ if (Private->IpChildHandle != NULL) {
+ Ping6DestroyIp6Instance (Private);
+ }
+
+ FreePool (Private);
+ }
+
+ return ShellStatus;
+}
+
+/**
+ Function for 'ping' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS The ping processed successfullly.
+ @retval others The ping processed unsuccessfully.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPing (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ EFI_IPv6_ADDRESS DstAddress;
+ EFI_IPv6_ADDRESS SrcAddress;
+ UINT64 BufferSize;
+ UINTN SendNumber;
+ LIST_ENTRY *ParamPackage;
+ CONST CHAR16 *ValueStr;
+ UINTN NonOptionCount;
+ UINT32 IpChoice;
+ CHAR16 *ProblemParam;
+
+ //
+ // we use IPv6 buffers to hold items...
+ // make sure this is enough space!
+ //
+ ASSERT(sizeof(EFI_IPv4_ADDRESS ) <= sizeof(EFI_IPv6_ADDRESS ));
+ ASSERT(sizeof(EFI_IP4_COMPLETION_TOKEN) <= sizeof(EFI_IP6_COMPLETION_TOKEN ));
+
+ IpChoice = PING_IP_CHOICE_IP4;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, &ProblemParam, TRUE, FALSE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ if (ShellCommandLineGetFlag (ParamPackage, L"-_ip6")) {
+ IpChoice = PING_IP_CHOICE_IP6;
+ }
+
+ //
+ // Parse the parameter of count number.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");
+ if (ValueStr != NULL) {
+ SendNumber = ShellStrToUintn (ValueStr);
+
+ //
+ // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
+ //
+ if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ } else {
+ SendNumber = DEFAULT_SEND_COUNT;
+ }
+ //
+ // Parse the parameter of buffer size.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
+ if (ValueStr != NULL) {
+ BufferSize = ShellStrToUintn (ValueStr);
+
+ //
+ // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
+ //
+ if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ } else {
+ BufferSize = DEFAULT_BUFFER_SIZE;
+ }
+
+ ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS));
+ ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));
+
+ //
+ // Parse the parameter of source ip address.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
+ if (ValueStr == NULL) {
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");
+ }
+
+ if (ValueStr != NULL) {
+ mSrcString = ValueStr;
+ if (IpChoice == PING_IP_CHOICE_IP6) {
+ Status = NetLibStrToIp6 (ValueStr, &SrcAddress);
+ } else {
+ Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);
+ }
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Parse the parameter of destination ip address.
+ //
+ NonOptionCount = ShellCommandLineGetCount(ParamPackage);
+ if (NonOptionCount < 2) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ping");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ if (NonOptionCount > 2) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle, L"ping");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);
+ if (ValueStr != NULL) {
+ mDstString = ValueStr;
+ if (IpChoice == PING_IP_CHOICE_IP6) {
+ Status = NetLibStrToIp6 (ValueStr, &DstAddress);
+ } else {
+ Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);
+ }
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+
+ //
+ // Enter into ping process.
+ //
+ ShellStatus = ShellPing (
+ (UINT32)SendNumber,
+ (UINT32)BufferSize,
+ &SrcAddress,
+ &DstAddress,
+ IpChoice
+ );
+
+ON_EXIT:
+ ShellCommandLineFreeVarList (ParamPackage);
+ return ShellStatus;
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c
new file mode 100644
index 000000000..9a2b23fdc
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c
@@ -0,0 +1,84 @@
+/** @file
+ Main file for NULL named library for network1 shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#include "UefiShellNetwork1CommandsLib.h"
+
+CONST CHAR16 gShellNetwork1FileName[] = L"ShellCommands";
+EFI_HII_HANDLE gShellNetwork1HiiHandle = NULL;
+
+/**
+ return the file name of the help text file if not using HII.
+
+ @return The string pointer to the file name.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameNetwork1 (
+ VOID
+ )
+{
+ return (gShellNetwork1FileName);
+}
+
+/**
+ Constructor for the Shell Network1 Commands library.
+
+ Install the handlers for Network1 UEFI Shell 2.0 profile commands.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS The shell command handlers were installed sucessfully.
+ @retval EFI_UNSUPPORTED The shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellNetwork1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellNetwork1HiiHandle = NULL;
+
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT3) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ gShellNetwork1HiiHandle = HiiAddPackages (&gShellNetwork1HiiGuid, gImageHandle, UefiShellNetwork1CommandsLibStrings, NULL);
+ if (gShellNetwork1HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+ //
+ // install our shell command handlers
+ //
+ ShellCommandRegisterCommandName(L"ping", ShellCommandRunPing , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_PING));
+ ShellCommandRegisterCommandName(L"ifconfig",ShellCommandRunIfconfig , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_IFCONFIG));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellNetwork1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellNetwork1HiiHandle != NULL) {
+ HiiRemovePackages(gShellNetwork1HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
diff --git a/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h
new file mode 100644
index 000000000..fddada2ef
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h
@@ -0,0 +1,70 @@
+/** @file
+ header file for NULL named library for network1 shell command functions.
+
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved. <BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_
+#define _UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_
+
+#include <Uefi.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/Ip6.h>
+#include <Protocol/Ip6Config.h>
+#include <Protocol/Ip4.h>
+#include <Protocol/Ip4Config2.h>
+#include <Protocol/Arp.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/NetLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+
+extern EFI_HII_HANDLE gShellNetwork1HiiHandle;
+
+/**
+ Function for 'ping' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPing (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'ifconfig' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIfconfig (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
new file mode 100644
index 000000000..1e6ce63e3
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
@@ -0,0 +1,64 @@
+## @file
+# Provides shell network1 functions
+#
+# Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved. <BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellNetwork1CommandsLib
+ FILE_GUID = 9A929F7E-3861-45ce-87AB-7371219AE255
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellNetwork1CommandsLibConstructor
+ DESTRUCTOR = ShellNetwork1CommandsLibDestructor
+
+[Sources.common]
+ UefiShellNetwork1CommandsLib.uni
+ UefiShellNetwork1CommandsLib.c
+ UefiShellNetwork1CommandsLib.h
+ Ping.c
+ Ifconfig.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ NetworkPkg/NetworkPkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+ NetLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Protocols]
+ gEfiCpuArchProtocolGuid ## CONSUMES
+ gEfiTimerArchProtocolGuid ## CONSUMES
+ gEfiIp6ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES
+
+ gEfiIp4ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp4ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gShellNetwork1HiiGuid ## SOMETIMES_CONSUMES ## HII
diff --git a/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
new file mode 100644
index 000000000..73cf96d9e
--- /dev/null
+++ b/roms/edk2/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
@@ -0,0 +1,176 @@
+// /**
+//
+// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved. <BR>
+// (C) Copyright 2017 Hewlett Packard Enterprise Development LP<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// Module Name:
+//
+// UefiShellNetwork1CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 network 1 commands
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM_OP2 #language en-US "%H%s%N: Invalid argument - '%H%s%N'. Expected '%B%s%N' or '%B%s%N'.\r\n"
+#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n"
+#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n"
+#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n"
+#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict.\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_FILE_AD #language en-US "%H%s%N: Access file error - '%H%s%N'\r\n"
+#string STR_GEN_CRLF #language en-US "\r\n"
+#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found.\r\n"
+#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n"
+#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_GEN_IS_DIR #language en-US "%H%s%N: '%H%s%N' is a directory\r\n"
+#string STR_GEN_PROTOCOL_NF #language en-US "%H%s%N: The protocol '%H%s%N' is required and not found (%g).\r\n"
+#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n"
+
+#string STR_PING_INVALID_SOURCE #language en-US "%Ping: Require source interface option\r\n"
+#string STR_PING_CONFIG #language en-US "Config %r\r\n"
+#string STR_PING_GETMODE #language en-US "GetModeData %r\r\n"
+#string STR_PING_GETDATA #language en-US "GetData %r\r\n"
+#string STR_PING_RECEIVE #language en-US "Receive %r\r\n"
+#string STR_PING_SEND_REQUEST #language en-US "Echo request sequence %d did not complete successfully.\r\n"
+#string STR_PING_NOSOURCE_INDO #language en-US "There are no sources in %s's multicast domain.\r\n"
+#string STR_PING_NETWORK_ERROR #language en-US "%H%s%N: Network function failed with %r\r\n"
+#string STR_PING_CONFIGD_NIC_NF #language en-US "%H%s%N: No configured interfaces were found.\r\n"
+#string STR_PING_NOROUTE_FOUND #language en-US "There is no route to the destination '%B%s%N' from the source '%B%s%N' was found.\r\n"
+#string STR_PING_START #language en-US "Ping %s %d data bytes.\r\n"
+#string STR_PING_TIMEOUT #language en-US "Echo request sequence %d timeout.\r\n"
+#string STR_PING_REPLY_INFO #language en-US "%d bytes from %s : icmp_seq=%d ttl=%d time%d~%dms\r\n"
+#string STR_PING_STAT #language en-US "\n%d packets transmitted, %d received, %d%% packet loss, time %dms\r\n"
+#string STR_PING_RTT #language en-US "\nRtt(round trip time) min=%d~%dms max=%d~%dms avg=%d~%dms\r\n"
+
+#string STR_IFCONFIG_UNSUPPORTED_OPTION #language en-US "The option '%H%s%N' is unsupported now.\n"
+#string STR_IFCONFIG_LACK_OPTION #language en-US "Flags lack. Please type 'ifConfig -?' for help info.\n"
+#string STR_IFCONFIG_LACK_INTERFACE #language en-US "Lack interface name.\n"
+#string STR_IFCONFIG_LACK_COMMAND #language en-US "Lack interface config option.\n"
+#string STR_IFCONFIG_INVALID_INTERFACE #language en-US "Invalid interface name.\n"
+#string STR_IFCONFIG_INVALID_IPADDRESS #language en-US "Invalid ipv4 address: '%H%s%N'\n"
+#string STR_IFCONFIG_INVALID_GATEWAY #language en-US "Invalid gateway address: '%H%s%N'\n"
+#string STR_IFCONFIG_DUPLICATE_COMMAND #language en-US "Duplicate commands. Bad command %H%s%N is skipped.\n"
+#string STR_IFCONFIG_CONFLICT_COMMAND #language en-US "Conflict commands. Bad command %H%s%N is skipped.\n"
+#string STR_IFCONFIG_UNKNOWN_COMMAND #language en-US "Unknown commands. Bad command %H%s%N is skipped.\n"
+#string STR_IFCONFIG_SET_ADDR_FAILED #language en-US "Failed to set address.\n"
+#string STR_IFCONFIG_ROUTES_SIZE #language en-US "\n%H Routes (%d entries):\n"
+#string STR_IFCONFIG_ROUTES_ENTRY_INDEX #language en-US "%H Entry[%d]\n"
+#string STR_IFCONFIG_SHOW_IP_ADDR #language en-US "%12s: %N%d.%d.%d.%d\n"
+#string STR_IFCONFIG_INFO_NEWLINE #language en-US "\n"
+#string STR_IFCONFIG_INFO_DNS_ADDR_BODY #language en-US "%8d.%d.%d.%d\n"
+#string STR_IFCONFIG_INFO_BREAK #language en-US "\n-----------------------------------------------------------------\n"
+#string STR_IFCONFIG_INFO_COLON #language en-US ":"
+#string STR_IFCONFIG_INFO_IF_NAME #language en-US "\n%Hname : %s%N\n"
+#string STR_IFCONFIG_INFO_MEDIA_STATE #language en-US "%HMedia State : %s%N\n"
+#string STR_IFCONFIG_INFO_POLICY_DHCP #language en-US "%Hpolicy : dhcp%N\n"
+#string STR_IFCONFIG_INFO_POLICY_MAN #language en-US "%Hpolicy : static%N\n"
+#string STR_IFCONFIG_INFO_MAC_ADDR_HEAD #language en-US "%Hmac addr : %N"
+#string STR_IFCONFIG_INFO_MAC_ADDR_BODY #language en-US "%02x"
+#string STR_IFCONFIG_INFO_IP_ADDR_HEAD #language en-US "\n%Hipv4 address : %N"
+#string STR_IFCONFIG_INFO_SUBNET_MASK_HEAD #language en-US "\n%Hsubnet mask : %N"
+#string STR_IFCONFIG_INFO_GATEWAY_HEAD #language en-US "\n%Hdefault gateway: %N"
+#string STR_IFCONFIG_INFO_DNS_ADDR_HEAD #language en-US "\n%HDNS server : %N\n"
+#string STR_IFCONFIG_INFO_IP_ADDR_BODY #language en-US "%d.%d.%d.%d\n"
+
+#string STR_GET_HELP_PING #language en-US ""
+".TH ping 0 "Ping the target host with an IPv4 stack."\r\n"
+".SH NAME\r\n"
+"Ping the target host with an IPv4 stack.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"PING [-n count] [-l size] [-s SourceIp] TargetIp\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -n - Specifies the number of echo request datagrams to be sent.\r\n"
+" -l - Specifies the size of the data buffer in the echo request datagram.\r\n"
+" -s - Specifies the source adapter as IPv4 address.\r\n"
+" SourceIp - Specifies the IPv4 address of the source machine.\r\n"
+" TargetIp - Specifies the IPv4 address of the target machine.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command uses the ICMPv4 ECHO_REQUEST datagram to elicit an\r\n"
+" ECHO_REPLY from a host.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To ping the target host with 64 bytes data:\r\n"
+" fs0:\> ping -l 64 192.168.0.1\r\n"
+" \r\n"
+" * To ping the target host by sending 20 echo request datagrams:\r\n"
+" fs0:\> ping -n 20 202.120.100.1\r\n"
+" \r\n"
+" * To ping the target host by specifying the source adapter as IPv4 address:\r\n"
+" fs0:\> ping -s 202.120.100.12 202.120.100.1\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_IFCONFIG #language en-US ""
+".TH ifconfig 0 "Modifies the default IP address of the UEFI IPv4 Network Stack."\r\n"
+".SH NAME\r\n"
+"Modifies the default IP address of the UEFI IPv4 Network Stack.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"IFCONFIG [-r [Name]] [-l [Name]]\r\n"
+"IFCONFIG [-s <Name> dhcp | <static <IP> <Mask> <Gateway>> | <dns <IP>>]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -r - Renew configuration of interface and set dhcp policy.\r\n"
+" -l - Lists the configuration.\r\n"
+" -s - Sets the configuration.\r\n"
+" Name - Specifies an adapter name (for example, eth0).\r\n"
+" IP - Specifies the IPv4 address in four integer values:\r\n"
+" - Example: 192.168.0.10\r\n"
+" SubnetMask - Specifies a subnet mask in four integer values:\r\n"
+" - Example: 255.255.255.0\r\n"
+" GatewayMask - Specifies a default gateway in four integer values:\r\n"
+" - Example: 192.168.0.1\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command modifies the default IP address for the UEFI IPv4\r\n"
+" network stack.\r\n"
+" 2. Use '-r' to renew configuration of interface and set dhcp policy.\r\n"
+" 3. Use '-l' to list the DNS and other address related settings for all\r\n"
+" interfaces or the specified interface.\r\n"
+" 4. Use '-s <Name> static <IP> <SubnetMask> <GatewayMask>' with \r\n"
+" static IPv4 address configuration for specified interface.\r\n"
+" 5. Use '-s <Name> dhcp' for DHCPv4 to request the IPv4 address\r\n"
+" configuration dynamically for specified interface.\r\n"
+" 6. Use '-s <Name> dns <IP>' must under manual policy.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To list the configuration for the eth0 interface:\r\n"
+" fs0:\> ifconfig -l eth0\r\n"
+" \r\n"
+" * To use DHCPv4 to request the IPv4 address configuration dynamically for the\r\n"
+" eth0 interface:\r\n"
+" fs0:\> ifconfig -s eth0 dhcp\r\n"
+" \r\n"
+" * To use the static IPv4 address configuration for the eth0 interface:\r\n"
+" fs0:\> ifconfig -s eth0 static 192.168.0.5 255.255.255.0 192.168.0.1\r\n"
+" \r\n"
+" * To configure DNS server address for the eth0 interface:\r\n"
+" fs0:\> ifconfig -s eth0 dns 192.168.0.8 192.168.0.9\r\n"
+
+
+