/** @file\r
The implementation for Ping6 application.\r
\r
- Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
#define PING6_MAX_SEND_NUMBER 10000\r
#define PING6_MAX_BUFFER_SIZE 32768\r
#define PING6_ONE_SECOND 10000000\r
-\r
-//\r
-// A similar amount of time that passes in femtoseconds\r
-// for each increment of TimerValue. It is for NT32 only.\r
-//\r
-#define NTTIMERPERIOD 358049\r
+#define STALL_1_MILLI_SECOND 1000\r
\r
#pragma pack(1)\r
\r
UINT16 Checksum;\r
UINT16 Identifier;\r
UINT16 SequenceNum;\r
- UINT64 TimeStamp;\r
+ UINT32 TimeStamp;\r
UINT8 Data[1];\r
} ICMP6_ECHO_REQUEST_REPLY;\r
\r
typedef struct _PING6_ICMP6_TX_INFO {\r
LIST_ENTRY Link;\r
UINT16 SequenceNum;\r
- UINT64 TimeStamp;\r
+ UINT32 TimeStamp;\r
EFI_IP6_COMPLETION_TOKEN *Token;\r
} PING6_ICMP6_TX_INFO;\r
\r
EFI_IP6_PROTOCOL *Ip6;\r
EFI_EVENT Timer;\r
\r
+ UINT32 TimerPeriod;\r
+ UINT32 RttTimerTick;\r
+ EFI_EVENT RttTimer;\r
+\r
EFI_STATUS Status;\r
LIST_ENTRY TxList;\r
EFI_IP6_COMPLETION_TOKEN RxToken;\r
//\r
CONST CHAR16 *mIp6DstString;\r
CONST CHAR16 *mIp6SrcString;\r
-UINT64 mFrequency = 0;\r
-UINT64 mIp6CurrentTick = 0;\r
EFI_CPU_ARCH_PROTOCOL *Cpu = NULL;\r
\r
+/**\r
+ RTT timer tick routine.\r
+\r
+ @param[in] Event A EFI_EVENT type event.\r
+ @param[in] Context The pointer to Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Ping6RttTimerTickRoutine (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ UINT32 *RttTimerTick;\r
\r
+ RttTimerTick = (UINT32*) Context;\r
+ (*RttTimerTick)++;\r
+}\r
\r
/**\r
- Reads and returns the current value of the Time.\r
+ Get the timer period of the system.\r
+\r
+ This function tries to get the system timer period by creating\r
+ an 1ms period timer.\r
\r
- @return The current tick value.\r
+ @return System timer period in MS, or 0 if operation failed.\r
\r
**/\r
-UINT64\r
-Ping6ReadTime ()\r
+UINT32\r
+Ping6GetTimerPeriod(\r
+ VOID\r
+ )\r
{\r
- UINT64 TimerPeriod;\r
- EFI_STATUS Status;\r
+ EFI_STATUS Status;\r
+ UINT32 RttTimerTick;\r
+ EFI_EVENT TimerEvent;\r
+ UINT32 StallCounter;\r
+ EFI_TPL OldTpl;\r
\r
- ASSERT (Cpu != NULL);\r
+ RttTimerTick = 0;\r
+ StallCounter = 0;\r
\r
- Status = Cpu->GetTimerValue (Cpu, 0, &mIp6CurrentTick, &TimerPeriod);\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ Ping6RttTimerTickRoutine,\r
+ &RttTimerTick,\r
+ &TimerEvent\r
+ );\r
if (EFI_ERROR (Status)) {\r
- //\r
- // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the\r
- // TimerPeriod by ourselves.\r
- //\r
- mIp6CurrentTick += 1000000;\r
+ return 0;\r
+ }\r
+\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+ Status = gBS->SetTimer (\r
+ TimerEvent,\r
+ TimerPeriodic,\r
+ TICKS_PER_MS\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->CloseEvent (TimerEvent);\r
+ return 0;\r
}\r
\r
- return mIp6CurrentTick;\r
+ while (RttTimerTick < 10) {\r
+ gBS->Stall (STALL_1_MILLI_SECOND);\r
+ ++StallCounter;\r
+ }\r
+\r
+ gBS->RestoreTPL (OldTpl);\r
+\r
+ gBS->SetTimer (TimerEvent, TimerCancel, 0);\r
+ gBS->CloseEvent (TimerEvent);\r
+\r
+ return StallCounter / RttTimerTick;\r
}\r
\r
+\r
/**\r
- Get and calculate the frequency in tick/ms.\r
- The result is saved in the globle variable mFrequency\r
+ Initialize the timer event for RTT (round trip time).\r
\r
- @retval EFI_SUCCESS Calculated the frequency successfully.\r
- @retval Others Failed to calculate the frequency.\r
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.\r
+\r
+ @retval EFI_SUCCESS RTT timer is started.\r
+ @retval Others Failed to start the RTT timer.\r
\r
**/\r
EFI_STATUS\r
-Ping6GetFrequency (\r
- VOID\r
+Ping6InitRttTimer (\r
+ IN PING6_PRIVATE_DATA *Private\r
)\r
{\r
- EFI_STATUS Status;\r
- UINT64 CurrentTick;\r
- UINT64 TimerPeriod;\r
+ EFI_STATUS Status;\r
\r
- Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu);\r
+ Private->TimerPeriod = Ping6GetTimerPeriod ();\r
+ if (Private->TimerPeriod == 0) {\r
+ return EFI_ABORTED;\r
+ }\r
\r
+ Private->RttTimerTick = 0;\r
+ Status = gBS->CreateEvent (\r
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,\r
+ TPL_NOTIFY,\r
+ Ping6RttTimerTickRoutine,\r
+ &Private->RttTimerTick,\r
+ &Private->RttTimer\r
+ );\r
if (EFI_ERROR (Status)) {\r
return Status;\r
}\r
\r
- Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);\r
-\r
+ Status = gBS->SetTimer (\r
+ Private->RttTimer,\r
+ TimerPeriodic,\r
+ TICKS_PER_MS\r
+ );\r
if (EFI_ERROR (Status)) {\r
- //\r
- // For NT32 Simulator only. 358049 is a similar value to keep timer granularity.\r
- // Set the timer period by ourselves.\r
- //\r
- TimerPeriod = (UINT64) NTTIMERPERIOD;\r
+ gBS->CloseEvent (Private->RttTimer);\r
+ return Status;\r
}\r
- //\r
- // The timer period is in femtosecond (1 femtosecond is 1e-15 second).\r
- // So 1e+12 is divided by timer period to produce the freq in tick/ms.\r
- //\r
- mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);\r
\r
return EFI_SUCCESS;\r
+\r
+}\r
+\r
+/**\r
+ Free RTT timer event resource.\r
+\r
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.\r
+\r
+**/\r
+VOID\r
+Ping6FreeRttTimer (\r
+ IN PING6_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ if (Private->RttTimer != NULL) {\r
+ gBS->SetTimer (Private->RttTimer, TimerCancel, 0);\r
+ gBS->CloseEvent (Private->RttTimer);\r
+ }\r
+}\r
+\r
+/**\r
+ Read the current time.\r
+\r
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.\r
+\r
+ @retval the current tick value.\r
+**/\r
+UINT32\r
+Ping6ReadTime (\r
+ IN PING6_PRIVATE_DATA *Private\r
+ )\r
+{\r
+ return Private->RttTimerTick;\r
}\r
\r
/**\r
Get and calculate the duration in ms.\r
\r
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.\r
@param[in] Begin The start point of time.\r
@param[in] End The end point of time.\r
\r
@return The duration in ms.\r
\r
**/\r
-UINT64\r
+UINT32\r
Ping6CalculateTick (\r
- IN UINT64 Begin,\r
- IN UINT64 End\r
+ IN PING6_PRIVATE_DATA *Private,\r
+ IN UINT32 Begin,\r
+ IN UINT32 End\r
)\r
{\r
- ASSERT (End > Begin);\r
- return DivU64x64Remainder (End - Begin, mFrequency, NULL);\r
+ if (End < Begin) {\r
+ return (0);\r
+ }\r
+\r
+ return (End - Begin) * Private->TimerPeriod;\r
+\r
}\r
\r
/**\r
EFI_IP6_RECEIVE_DATA *RxData;\r
ICMP6_ECHO_REQUEST_REPLY *Reply;\r
UINT32 PayLoad;\r
- UINT64 Rtt;\r
- CHAR8 Near;\r
+ UINT32 Rtt;\r
\r
Private = (PING6_PRIVATE_DATA *) Context;\r
\r
//\r
// Display statistics on this icmp6 echo reply packet.\r
//\r
- Rtt = Ping6CalculateTick (Reply->TimeStamp, Ping6ReadTime ());\r
- if (Rtt != 0) {\r
- Near = (CHAR8) '=';\r
- } else {\r
- Near = (CHAR8) '<';\r
- }\r
+ Rtt = Ping6CalculateTick (Private, Reply->TimeStamp, Ping6ReadTime (Private));\r
\r
Private->RttSum += Rtt;\r
Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin;\r
mIp6DstString,\r
Reply->SequenceNum,\r
RxData->Header->HopLimit,\r
- Near,\r
- Rtt\r
+ Rtt,\r
+ Rtt + Private->TimerPeriod\r
);\r
\r
ON_EXIT:\r
Status = Private->Ip6->Receive (Private->Ip6, RxToken);\r
\r
if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_RECEIVE), gShellNetwork2HiiHandle, Status);\r
Private->Status = EFI_ABORTED;\r
}\r
} else {\r
EFI_IP6_COMPLETION_TOKEN *\r
Ping6GenerateToken (\r
IN PING6_PRIVATE_DATA *Private,\r
- IN UINT64 TimeStamp,\r
+ IN UINT32 TimeStamp,\r
IN UINT16 SequenceNum\r
)\r
{\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- TxInfo->TimeStamp = Ping6ReadTime ();\r
+ TxInfo->TimeStamp = Ping6ReadTime (Private);\r
TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);\r
\r
TxInfo->Token = Ping6GenerateToken (\r
\r
Private->RxToken.Status = EFI_NOT_READY;\r
\r
- return Private->Ip6->Receive (Private->Ip6, &Private->RxToken);\r
+ Status = Private->Ip6->Receive (Private->Ip6, &Private->RxToken);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_RECEIVE), gShellNetwork2HiiHandle, Status);\r
+ }\r
+ return Status;\r
}\r
\r
/**\r
//\r
NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {\r
TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);\r
- Time = Ping6CalculateTick (TxInfo->TimeStamp, Ping6ReadTime ());\r
+ Time = Ping6CalculateTick (Private, TxInfo->TimeStamp, Ping6ReadTime (Private));\r
\r
//\r
// Remove the timeout echo request from txlist.\r
UINTN HandleIndex;\r
UINTN HandleNum;\r
EFI_HANDLE *HandleBuffer;\r
+ BOOLEAN UnspecifiedSrc;\r
+ EFI_STATUS MediaStatus;\r
EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb;\r
EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;\r
EFI_IP6_CONFIG_DATA Ip6Config;\r
EFI_IPv6_ADDRESS *Addr;\r
UINTN AddrIndex;\r
\r
- HandleBuffer = NULL;\r
- Ip6Sb = NULL;\r
- IfInfo = NULL;\r
- IfInfoSize = 0;\r
+ HandleBuffer = NULL;\r
+ UnspecifiedSrc = FALSE;\r
+ MediaStatus = EFI_SUCCESS;\r
+ Ip6Sb = NULL;\r
+ IfInfo = NULL;\r
+ IfInfoSize = 0;\r
\r
//\r
// Locate all the handles with ip6 service binding protocol.\r
if (EFI_ERROR (Status) || (HandleNum == 0)) {\r
return EFI_ABORTED;\r
}\r
+\r
+ if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) {\r
+ //\r
+ // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected.\r
+ //\r
+ UnspecifiedSrc = TRUE;\r
+ }\r
+\r
//\r
- // Source address is required when pinging a link-local address on multi-\r
- // interfaces host.\r
+ // Source address is required when pinging a link-local address.\r
//\r
- if (NetIp6IsLinkLocalAddr (&Private->DstAddress) &&\r
- NetIp6IsUnspecifiedAddr (&Private->SrcAddress) &&\r
- (HandleNum > 1)) {\r
+ if (NetIp6IsLinkLocalAddr (&Private->DstAddress) && UnspecifiedSrc) {\r
ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), gShellNetwork2HiiHandle);\r
Status = EFI_INVALID_PARAMETER;\r
goto ON_ERROR;\r
}\r
+\r
//\r
// For each ip6 protocol, check interface addresses list.\r
//\r
IfInfo = NULL;\r
IfInfoSize = 0;\r
\r
+ if (UnspecifiedSrc) {\r
+ //\r
+ // Check media.\r
+ //\r
+ NetLibDetectMediaWaitTimeout (HandleBuffer[HandleIndex], 0, &MediaStatus);\r
+ if (MediaStatus != EFI_SUCCESS) {\r
+ //\r
+ // Skip this one.\r
+ //\r
+ continue;\r
+ }\r
+ }\r
+\r
Status = gBS->HandleProtocol (\r
HandleBuffer[HandleIndex],\r
&gEfiIp6ServiceBindingProtocolGuid,\r
goto ON_ERROR;\r
}\r
\r
- if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) {\r
- //\r
- // No need to match interface address.\r
- //\r
- break;\r
- } else {\r
- //\r
- // Ip6config protocol and ip6 service binding protocol are installed\r
- // on the same handle.\r
- //\r
- Status = gBS->HandleProtocol (\r
- HandleBuffer[HandleIndex],\r
- &gEfiIp6ConfigProtocolGuid,\r
- (VOID **) &Ip6Cfg\r
- );\r
+ //\r
+ // Ip6config protocol and ip6 service binding protocol are installed\r
+ // on the same handle.\r
+ //\r
+ Status = gBS->HandleProtocol (\r
+ HandleBuffer[HandleIndex],\r
+ &gEfiIp6ConfigProtocolGuid,\r
+ (VOID **) &Ip6Cfg\r
+ );\r
\r
- if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
- }\r
- //\r
- // Get the interface information size.\r
- //\r
- Status = Ip6Cfg->GetData (\r
- Ip6Cfg,\r
- Ip6ConfigDataTypeInterfaceInfo,\r
- &IfInfoSize,\r
- NULL\r
- );\r
-\r
- if (Status != EFI_BUFFER_TOO_SMALL) {\r
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
- goto ON_ERROR;\r
- }\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_ERROR;\r
+ }\r
+ //\r
+ // Get the interface information size.\r
+ //\r
+ Status = Ip6Cfg->GetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeInterfaceInfo,\r
+ &IfInfoSize,\r
+ NULL\r
+ );\r
+\r
+ if (Status != EFI_BUFFER_TOO_SMALL) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+ goto ON_ERROR;\r
+ }\r
\r
- IfInfo = AllocateZeroPool (IfInfoSize);\r
+ IfInfo = AllocateZeroPool (IfInfoSize);\r
\r
- if (IfInfo == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto ON_ERROR;\r
- }\r
- //\r
- // Get the interface info.\r
- //\r
- Status = Ip6Cfg->GetData (\r
- Ip6Cfg,\r
- Ip6ConfigDataTypeInterfaceInfo,\r
- &IfInfoSize,\r
- IfInfo\r
- );\r
+ if (IfInfo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto ON_ERROR;\r
+ }\r
+ //\r
+ // Get the interface info.\r
+ //\r
+ Status = Ip6Cfg->GetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeInterfaceInfo,\r
+ &IfInfoSize,\r
+ IfInfo\r
+ );\r
\r
- if (EFI_ERROR (Status)) {\r
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
- goto ON_ERROR;\r
- }\r
- //\r
- // Check whether the source address is one of the interface addresses.\r
- //\r
- for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {\r
+ if (EFI_ERROR (Status)) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);\r
+ goto ON_ERROR;\r
+ }\r
+ //\r
+ // Check whether the source address is one of the interface addresses.\r
+ //\r
+ for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {\r
+ Addr = &(IfInfo->AddressInfo[AddrIndex].Address);\r
\r
- Addr = &(IfInfo->AddressInfo[AddrIndex].Address);\r
- if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
+ if (UnspecifiedSrc) {\r
+ if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {\r
//\r
- // Match a certain interface address.\r
+ // Select the interface automatically.\r
//\r
+ CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));\r
break;\r
}\r
- }\r
-\r
- if (AddrIndex < IfInfo->AddressInfoCount) {\r
+ } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {\r
//\r
- // Found a nic handle with right interface address.\r
+ // Match a certain interface address.\r
//\r
break;\r
}\r
}\r
\r
+ if (AddrIndex < IfInfo->AddressInfoCount) {\r
+ //\r
+ // Found a nic handle with right interface address.\r
+ //\r
+ break;\r
+ }\r
+\r
FreePool (IfInfo);\r
IfInfo = NULL;\r
}\r
//\r
\r
if (HandleIndex == HandleNum) {\r
- ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SOURCE_NOT_FOUND), gShellNetwork2HiiHandle, mIp6SrcString);\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_CONFIGD_NIC_NF), gShellNetwork2HiiHandle);\r
Status = EFI_NOT_FOUND;\r
goto ON_ERROR;\r
}\r
ShellStatus = SHELL_SUCCESS;\r
Private = AllocateZeroPool (sizeof (PING6_PRIVATE_DATA));\r
\r
- ASSERT (Private != NULL);\r
+ if (Private == NULL) {\r
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"Ping6");\r
+ ShellStatus = SHELL_OUT_OF_RESOURCES;\r
+ goto ON_EXIT;\r
+ }\r
\r
Private->ImageHandle = ImageHandle;\r
Private->SendNum = SendNumber;\r
ShellStatus = SHELL_ACCESS_DENIED;\r
goto ON_EXIT;\r
}\r
+\r
+ //\r
+ // Start a timer to calculate the RTT.\r
+ //\r
+ Status = Ping6InitRttTimer (Private);\r
+ if (EFI_ERROR (Status)) {\r
+ ShellStatus = SHELL_ACCESS_DENIED;\r
+ goto ON_EXIT;\r
+ }\r
+\r
//\r
// Create a ipv6 token to send the first icmp6 echo request packet.\r
//\r
STRING_TOKEN (STR_PING6_RTT),\r
gShellNetwork2HiiHandle,\r
Private->RttMin,\r
+ Private->RttMin + Private->TimerPeriod,\r
Private->RttMax,\r
- DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)\r
+ Private->RttMax + Private->TimerPeriod,\r
+ DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL),\r
+ DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL) + Private->TimerPeriod\r
);\r
}\r
\r
Ping6DestroyTxInfo (TxInfo);\r
}\r
\r
+ Ping6FreeRttTimer (Private);\r
+\r
if (Private->Timer != NULL) {\r
gBS->CloseEvent (Private->Timer);\r
}\r
BufferSize = 16;\r
\r
//\r
- // Parse the paramter of count number.\r
+ // Parse the parameter of count number.\r
//\r
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");\r
ValueStrPtr = ValueStr;\r
}\r
}\r
//\r
- // Parse the paramter of buffer size.\r
+ // Parse the parameter of buffer size.\r
//\r
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");\r
ValueStrPtr = ValueStr;\r
ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));\r
\r
//\r
- // Parse the paramter of source ip address.\r
+ // Parse the parameter of source ip address.\r
//\r
ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");\r
ValueStrPtr = ValueStr;\r
}\r
}\r
//\r
- // Parse the paramter of destination ip address.\r
+ // Parse the parameter of destination ip address.\r
//\r
NonOptionCount = ShellCommandLineGetCount(ParamPackage);\r
ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32)(NonOptionCount-1));\r
goto ON_EXIT;\r
}\r
}\r
- //\r
- // Get frequency to calculate the time from ticks.\r
- //\r
- Status = Ping6GetFrequency ();\r
\r
- if (EFI_ERROR(Status)) {\r
- ShellStatus = SHELL_ACCESS_DENIED;\r
- goto ON_EXIT;\r
- }\r
//\r
// Enter into ping6 process.\r
//\r