diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /ShellPkg/Library/UefiShellNetwork1CommandsLib | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'ShellPkg/Library/UefiShellNetwork1CommandsLib')
6 files changed, 3573 insertions, 3573 deletions
diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c index 71b08bdff1..27b07920bb 100644 --- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c +++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c @@ -1,1447 +1,1447 @@ -/** @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;
-}
+/** @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/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c index 21e09db70d..cfd3204b1a 100644 --- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c +++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c @@ -1,1731 +1,1731 @@ -/** @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;
- UINT32 TimerPeriod;
-
- RttTimerTick = 0;
- StallCounter = 0;
- TimerPeriod = 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);
-
- TimerPeriod = StallCounter / RttTimerTick;
- if (TimerPeriod != 0) {
- return TimerPeriod;
- } else {
- return 1;
- }
-}
-
-/**
- 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 routine.
-
- @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;
-}
+/** @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; + UINT32 TimerPeriod; + + RttTimerTick = 0; + StallCounter = 0; + TimerPeriod = 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); + + TimerPeriod = StallCounter / RttTimerTick; + if (TimerPeriod != 0) { + return TimerPeriod; + } else { + return 1; + } +} + +/** + 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 routine. + + @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/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c index 4d4bc2b4ab..a9f39eee11 100644 --- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c +++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c @@ -1,86 +1,86 @@ -/** @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 successfully.
- @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);
-}
+/** @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 successfully. + @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/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h index 4c16efa37a..b7cad4af97 100644 --- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h +++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h @@ -1,69 +1,69 @@ -/** @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
+/** @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/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf index 1e6ce63e3e..8746370729 100644 --- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf +++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf @@ -1,64 +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
+## @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/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni index 37fd4a1192..d2a16c4da4 100644 --- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni +++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni @@ -1,176 +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"
-
-
-
+// /** +// +// (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" + + + |
