Example #1
0
EFIAPI
AcquireSpinLock (
  IN OUT  SPIN_LOCK                 *SpinLock
  )
{
  UINT64                            Tick;
  UINT64                            Start, End;
  UINT64                            Timeout;

  Tick = 0;
  Start = 0;
  End = 0;
  if (PcdGet32 (PcdSpinLockTimeout) > 0) {
    Tick = GetPerformanceCounter ();
    Timeout = DivU64x32 (
                MultU64x32 (
                  GetPerformanceCounterProperties (&Start, &End),
                  PcdGet32 (PcdSpinLockTimeout)
                  ),
                1000000
                );
    if (Start < End) {
      Tick += Timeout;
    } else {
      Tick -= Timeout;
    }
  }

  while (!AcquireSpinLockOrFail (SpinLock)) {
    CpuPause ();
    ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ()));
  }
  return SpinLock;
}
Example #2
0
/**
  Stalls the CPU for at least the given number of nanoseconds.

  Stalls the CPU for the number of nanoseconds specified by NanoSeconds.

  @param  NanoSeconds The minimum number of nanoseconds to delay.

  @return The value of NanoSeconds inputted.

**/
UINTN
EFIAPI
NanoSecondDelay (
    IN      UINTN                     NanoSeconds
)
{
    InternalIpfDelay (
        GetPerformanceCounterProperties (NULL, NULL) *
        NanoSeconds /
        1000000000
    );
    return NanoSeconds;
}
Example #3
0
/**
  Entry point of the Timestamp Protocol driver.

  @param  ImageHandle   The image handle of this driver.
  @param  SystemTable   The pointer of EFI_SYSTEM_TABLE.

  @retval EFI_SUCCESS   Watchdog Timer Architectural Protocol successfully installed.

**/
EFI_STATUS
EFIAPI
TimestampDriverInitialize (
  IN EFI_HANDLE        ImageHandle,
  IN EFI_SYSTEM_TABLE  *SystemTable
  )
{
  EFI_STATUS  Status;
  
  EFI_HANDLE  TimestampHandle;
  TimestampHandle = NULL;
  
  //
  // Get the start value, end value and frequency in Timerlib
  //
  mTimestampProperties.Frequency = GetPerformanceCounterProperties(&mTimerLibStartValue, &mTimerLibEndValue);
  
  //
  // Set the EndValue 
  //
  if (mTimerLibEndValue > mTimerLibStartValue) {
    mTimestampProperties.EndValue = mTimerLibEndValue - mTimerLibStartValue;
  } else {
    mTimestampProperties.EndValue = mTimerLibStartValue - mTimerLibEndValue;
  }
  
  DEBUG ((EFI_D_INFO, "TimerFrequency:0x%lx, TimerLibStartTime:0x%lx, TimerLibEndtime:0x%lx\n", mTimestampProperties.Frequency, mTimerLibStartValue, mTimerLibEndValue));
  
  //
  // Install the Timestamp Protocol onto a new handle
  //
  Status = gBS->InstallMultipleProtocolInterfaces (
                  &TimestampHandle,
                  &gEfiTimestampProtocolGuid,
                  &mTimestamp,
                  NULL
                  );
                  
  ASSERT_EFI_ERROR (Status);

  return EFI_SUCCESS;
}
Example #4
0
/**
  Initialize Timer for SMM AP Sync.

**/
VOID
InitializeSmmTimer (
  VOID
  )
{
  UINT64  TimerFrequency;
  UINT64  Start;
  UINT64  End;

  TimerFrequency = GetPerformanceCounterProperties (&Start, &End);
  mTimeoutTicker = DivU64x32 (
                     MultU64x64(TimerFrequency, PcdGet64 (PcdCpuSmmApSyncTimeout)),
                     1000 * 1000
                     );
  if (End < Start) {
    mCountDown = TRUE;
    mCycle = Start - End;
  } else {
    mCountDown = FALSE;
    mCycle = End - Start;
  }
}
Example #5
0
/**

  Writes performance data of booting into the allocated memory.
  OS can process these records.

  @param  Event                 The triggered event.
  @param  Context               Context for this event.

**/
VOID
EFIAPI
WriteBootToOsPerformanceData (
  IN EFI_EVENT  Event,
  IN VOID       *Context
  )
{
  EFI_STATUS                Status;
  UINT32                    LimitCount;
  EFI_HANDLE                *Handles;
  UINTN                     NoHandles;
  CHAR8                     GaugeString[PERF_TOKEN_SIZE];
  UINT8                     *Ptr;
  UINT32                    Index;
  UINT64                    Ticker;
  UINT64                    Freq;
  UINT32                    Duration;
  UINTN                     LogEntryKey;
  CONST VOID                *Handle;
  CONST CHAR8               *Token;
  CONST CHAR8               *Module;
  UINT64                    StartTicker;
  UINT64                    EndTicker;
  UINT64                    StartValue;
  UINT64                    EndValue;
  BOOLEAN                   CountUp;
  UINTN                     EntryIndex;
  UINTN                     NumPerfEntries;
  //
  // List of flags indicating PerfEntry contains DXE handle
  //
  BOOLEAN                   *PerfEntriesAsDxeHandle;
  UINTN                     VarSize;

  //
  // Record the performance data for End of BDS
  //
  PERF_END(NULL, "BDS", NULL, 0);

  //
  // Retrieve time stamp count as early as possible
  //
  Ticker  = GetPerformanceCounter ();

  Freq    = GetPerformanceCounterProperties (&StartValue, &EndValue);
  
  Freq    = DivU64x32 (Freq, 1000);

  mPerfHeader.CpuFreq = Freq;

  //
  // Record BDS raw performance data
  //
  if (EndValue >= StartValue) {
    mPerfHeader.BDSRaw = Ticker - StartValue;
    CountUp            = TRUE;
  } else {
    mPerfHeader.BDSRaw = StartValue - Ticker;
    CountUp            = FALSE;
  }

  if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
    VarSize = sizeof (EFI_PHYSICAL_ADDRESS);
    Status = gRT->GetVariable (
                    L"PerfDataMemAddr",
                    &gPerformanceProtocolGuid,
                    NULL,
                    &VarSize,
                    &mAcpiLowMemoryBase
                    );
    if (EFI_ERROR (Status)) {
      //
      // Fail to get the variable, return.
      //
      return;
    }
  }

  //
  // Put Detailed performance data into memory
  //
  Handles = NULL;
  Status = gBS->LocateHandleBuffer (
                  AllHandles,
                  NULL,
                  NULL,
                  &NoHandles,
                  &Handles
                  );
  if (EFI_ERROR (Status)) {
    return ;
  }

  Ptr        = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
  LimitCount = (UINT32) (PERF_DATA_MAX_LENGTH - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);

  NumPerfEntries = 0;
  LogEntryKey    = 0;
  while ((LogEntryKey = GetPerformanceMeasurement (
                          LogEntryKey,
                          &Handle,
                          &Token,
                          &Module,
                          &StartTicker,
                          &EndTicker)) != 0) {
    NumPerfEntries++;
  }
  PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
  ASSERT (PerfEntriesAsDxeHandle != NULL);
  
  //
  // Get DXE drivers performance
  //
  for (Index = 0; Index < NoHandles; Index++) {
    Ticker = 0;
    LogEntryKey = 0;
    EntryIndex  = 0;
    while ((LogEntryKey = GetPerformanceMeasurement (
                            LogEntryKey,
                            &Handle,
                            &Token,
                            &Module,
                            &StartTicker,
                            &EndTicker)) != 0) {
      if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
        PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
      }
      EntryIndex++;
      if ((Handle == Handles[Index]) && (EndTicker != 0)) {
        if (StartTicker == 1) {
          StartTicker = StartValue;
        }
        if (EndTicker == 1) {
          EndTicker = StartValue;
        }
        Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
      }
    }

    Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);

    if (Duration > 0) {

      GetNameFromHandle (Handles[Index], GaugeString);

      AsciiStrCpyS (mPerfData.Token, PERF_TOKEN_SIZE, GaugeString);
      mPerfData.Duration = Duration;

      CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
      Ptr += sizeof (PERF_DATA);

      mPerfHeader.Count++;
      if (mPerfHeader.Count == LimitCount) {
        goto Done;
      }
    }
  }

  //
  // Get inserted performance data
  //
  LogEntryKey = 0;
  EntryIndex  = 0;
  while ((LogEntryKey = GetPerformanceMeasurement (
                          LogEntryKey,
                          &Handle,
                          &Token,
                          &Module,
                          &StartTicker,
                          &EndTicker)) != 0) {
    if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {

      ZeroMem (&mPerfData, sizeof (PERF_DATA));

      AsciiStrnCpyS (mPerfData.Token, PERF_TOKEN_SIZE, Token, PERF_TOKEN_LENGTH);
      if (StartTicker == 1) {
        StartTicker = StartValue;
      }
      if (EndTicker == 1) {
        EndTicker = StartValue;
      }
      Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);

      mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);

      CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
      Ptr += sizeof (PERF_DATA);

      mPerfHeader.Count++;
      if (mPerfHeader.Count == LimitCount) {
        goto Done;
      }
    }
    EntryIndex++;
  }

Done:

  FreePool (Handles);
  FreePool (PerfEntriesAsDxeHandle);

  mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;

  //
  // Put performance data to Reserved memory
  //
  CopyMem (
    (UINTN *) (UINTN) mAcpiLowMemoryBase,
    &mPerfHeader,
    sizeof (PERF_HEADER)
    );

  return ;
}
EFIAPI
AcquireSpinLock (
  IN OUT  SPIN_LOCK                 *SpinLock
  )
{
  UINT64  Current;
  UINT64  Previous;
  UINT64  Total;
  UINT64  Start;
  UINT64  End;
  UINT64  Timeout;
  INT64   Cycle;
  INT64   Delta;

  if (PcdGet32 (PcdSpinLockTimeout) > 0) {
    //
    // Get the current timer value
    //
    Current = GetPerformanceCounter();

    //
    // Initialize local variables
    //
    Start = 0;
    End   = 0;
    Total = 0;

    //
    // Retrieve the performance counter properties and compute the number of performance
    // counter ticks required to reach the timeout
    //
    Timeout = DivU64x32 (
                MultU64x32 (
                  GetPerformanceCounterProperties (&Start, &End),
                  PcdGet32 (PcdSpinLockTimeout)
                  ),
                1000000
                );
    Cycle = End - Start;
    if (Cycle < 0) {
      Cycle = -Cycle;
    }
    Cycle++;

    while (!AcquireSpinLockOrFail (SpinLock)) {
      CpuPause ();
      Previous = Current;
      Current  = GetPerformanceCounter();
      Delta = (INT64) (Current - Previous);
      if (Start > End) {
        Delta = -Delta;
      }
      if (Delta < 0) {
        Delta += Cycle;
      }
      Total += Delta;
      ASSERT (Total < Timeout);
    }
  } else {
    while (!AcquireSpinLockOrFail (SpinLock)) {
      CpuPause ();
    }
  }
  return SpinLock;
}
Example #7
0
/**

  Allocates a block of memory and writes performance data of booting into it.
  OS can processing these record.

**/
VOID
WriteBootToOsPerformanceData (
    VOID
)
{
    EFI_STATUS                Status;
    UINT32                    AcpiLowMemoryLength;
    UINT32                    LimitCount;
    EFI_HANDLE                *Handles;
    UINTN                     NoHandles;
    CHAR8                     GaugeString[PERF_TOKEN_LENGTH];
    UINT8                     *Ptr;
    UINT32                    Index;
    UINT64                    Ticker;
    UINT64                    Freq;
    UINT32                    Duration;
    UINTN                     LogEntryKey;
    CONST VOID                *Handle;
    CONST CHAR8               *Token;
    CONST CHAR8               *Module;
    UINT64                    StartTicker;
    UINT64                    EndTicker;
    UINT64                    StartValue;
    UINT64                    EndValue;
    BOOLEAN                   CountUp;
    UINTN                     EntryIndex;
    UINTN                     NumPerfEntries;
    //
    // List of flags indicating PerfEntry contains DXE handle
    //
    BOOLEAN                   *PerfEntriesAsDxeHandle;

    //
    // Retrieve time stamp count as early as possible
    //
    Ticker  = GetPerformanceCounter ();

    Freq    = GetPerformanceCounterProperties (&StartValue, &EndValue);

    Freq    = DivU64x32 (Freq, 1000);

    mPerfHeader.CpuFreq = Freq;

    //
    // Record BDS raw performance data
    //
    if (EndValue >= StartValue) {
        mPerfHeader.BDSRaw = Ticker - StartValue;
        CountUp            = TRUE;
    } else {
        mPerfHeader.BDSRaw = StartValue - Ticker;
        CountUp            = FALSE;
    }

    //
    // Put Detailed performance data into memory
    //
    Handles = NULL;
    Status = gBS->LocateHandleBuffer (
                 AllHandles,
                 NULL,
                 NULL,
                 &NoHandles,
                 &Handles
             );
    if (EFI_ERROR (Status)) {
        return ;
    }


    AcpiLowMemoryLength = 0x4000;
    if (mAcpiLowMemoryBase == 0x0FFFFFFFF) {
        //
        // Allocate a block of memory that contain performance data to OS
        //
        Status = gBS->AllocatePages (
                     AllocateMaxAddress,
                     EfiReservedMemoryType,
                     EFI_SIZE_TO_PAGES (AcpiLowMemoryLength),
                     &mAcpiLowMemoryBase
                 );
        if (EFI_ERROR (Status)) {
            FreePool (Handles);
            return ;
        }
    }


    Ptr        = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER));
    LimitCount = (AcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA);

    NumPerfEntries = 0;
    LogEntryKey    = 0;
    while ((LogEntryKey = GetPerformanceMeasurement (
                              LogEntryKey,
                              &Handle,
                              &Token,
                              &Module,
                              &StartTicker,
                              &EndTicker)) != 0) {
        NumPerfEntries++;
    }
    PerfEntriesAsDxeHandle = AllocateZeroPool (NumPerfEntries * sizeof (BOOLEAN));
    ASSERT (PerfEntriesAsDxeHandle != NULL);

    //
    // Get DXE drivers performance
    //
    for (Index = 0; Index < NoHandles; Index++) {
        Ticker = 0;
        LogEntryKey = 0;
        EntryIndex  = 0;
        while ((LogEntryKey = GetPerformanceMeasurement (
                                  LogEntryKey,
                                  &Handle,
                                  &Token,
                                  &Module,
                                  &StartTicker,
                                  &EndTicker)) != 0) {
            if (Handle == Handles[Index] && !PerfEntriesAsDxeHandle[EntryIndex]) {
                PerfEntriesAsDxeHandle[EntryIndex] = TRUE;
            }
            EntryIndex++;
            if ((Handle == Handles[Index]) && (EndTicker != 0)) {
                if (StartTicker == 1) {
                    StartTicker = StartValue;
                }
                if (EndTicker == 1) {
                    EndTicker = StartValue;
                }
                Ticker += CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);
            }
        }

        Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);

        if (Duration > 0) {

            GetNameFromHandle (Handles[Index], GaugeString);

            AsciiStrCpy (mPerfData.Token, GaugeString);
            mPerfData.Duration = Duration;

            CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
            Ptr += sizeof (PERF_DATA);

            mPerfHeader.Count++;
            if (mPerfHeader.Count == LimitCount) {
                goto Done;
            }
        }
    }

    //
    // Get inserted performance data
    //
    LogEntryKey = 0;
    EntryIndex  = 0;
    while ((LogEntryKey = GetPerformanceMeasurement (
                              LogEntryKey,
                              &Handle,
                              &Token,
                              &Module,
                              &StartTicker,
                              &EndTicker)) != 0) {
        if (!PerfEntriesAsDxeHandle[EntryIndex] && EndTicker != 0) {

            ZeroMem (&mPerfData, sizeof (PERF_DATA));

            AsciiStrnCpy (mPerfData.Token, Token, PERF_TOKEN_LENGTH);
            if (StartTicker == 1) {
                StartTicker = StartValue;
            }
            if (EndTicker == 1) {
                EndTicker = StartValue;
            }
            Ticker = CountUp ? (EndTicker - StartTicker) : (StartTicker - EndTicker);

            mPerfData.Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);

            CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA));
            Ptr += sizeof (PERF_DATA);

            mPerfHeader.Count++;
            if (mPerfHeader.Count == LimitCount) {
                goto Done;
            }
        }
        EntryIndex++;
    }

Done:

    FreePool (Handles);
    FreePool (PerfEntriesAsDxeHandle);

    mPerfHeader.Signiture = PERFORMANCE_SIGNATURE;

    //
    // Put performance data to Reserved memory
    //
    CopyMem (
        (UINTN *) (UINTN) mAcpiLowMemoryBase,
        &mPerfHeader,
        sizeof (PERF_HEADER)
    );

    gRT->SetVariable (
        L"PerfDataMemAddr",
        &gPerformanceProtocolGuid,
        EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
        sizeof (EFI_PHYSICAL_ADDRESS),
        &mAcpiLowMemoryBase
    );

    return ;
}
Example #8
0
File: Dp.c Project: OznOg/edk2
/**
  Dump performance data.
  
  @param[in]  ImageHandle     The image handle.
  @param[in]  SystemTable     The system table.

  @retval EFI_SUCCESS            Command completed successfully.
  @retval EFI_INVALID_PARAMETER  Command usage error.
  @retval EFI_ABORTED            The user aborts the operation.
  @retval value                  Unknown error.
**/
EFI_STATUS
EFIAPI
InitializeDp (
  IN EFI_HANDLE               ImageHandle,
  IN EFI_SYSTEM_TABLE         *SystemTable
  )
{
  UINT64                    Freq;
  UINT64                    Ticker;
  UINT32                    ListIndex;
  
  LIST_ENTRY                *ParamPackage;
  CONST CHAR16              *CmdLineArg;
  EFI_STRING                StringPtr;
  UINTN                     Number2Display;

  EFI_STATUS                Status;
  BOOLEAN                   SummaryMode;
  BOOLEAN                   VerboseMode;
  BOOLEAN                   AllMode;
  BOOLEAN                   RawMode;
  BOOLEAN                   TraceMode;
  BOOLEAN                   ProfileMode;
  BOOLEAN                   ExcludeMode;
  BOOLEAN                   CumulativeMode;
  CONST CHAR16              *CustomCumulativeToken;
  PERF_CUM_DATA             *CustomCumulativeData;

  EFI_STRING                StringDpOptionQh;
  EFI_STRING                StringDpOptionLh;
  EFI_STRING                StringDpOptionUh;
  EFI_STRING                StringDpOptionLv;
  EFI_STRING                StringDpOptionUs;
  EFI_STRING                StringDpOptionLs;
  EFI_STRING                StringDpOptionUa;
  EFI_STRING                StringDpOptionUr;
  EFI_STRING                StringDpOptionUt;
  EFI_STRING                StringDpOptionUp;
  EFI_STRING                StringDpOptionLx;
  EFI_STRING                StringDpOptionLn;
  EFI_STRING                StringDpOptionLt;
  EFI_STRING                StringDpOptionLi;
  EFI_STRING                StringDpOptionLc;
  
  SummaryMode     = FALSE;
  VerboseMode     = FALSE;
  AllMode         = FALSE;
  RawMode         = FALSE;
  TraceMode       = FALSE;
  ProfileMode     = FALSE;
  ExcludeMode     = FALSE;
  CumulativeMode = FALSE;
  CustomCumulativeData = NULL;

  StringDpOptionQh = NULL;
  StringDpOptionLh = NULL;
  StringDpOptionUh = NULL;
  StringDpOptionLv = NULL;
  StringDpOptionUs = NULL;
  StringDpOptionLs = NULL;
  StringDpOptionUa = NULL;
  StringDpOptionUr = NULL;
  StringDpOptionUt = NULL;
  StringDpOptionUp = NULL;
  StringDpOptionLx = NULL;
  StringDpOptionLn = NULL;
  StringDpOptionLt = NULL;
  StringDpOptionLi = NULL;
  StringDpOptionLc = NULL;
  StringPtr        = NULL;

  // Get DP's entry time as soon as possible.
  // This is used as the Shell-Phase end time.
  //
  Ticker  = GetPerformanceCounter ();

  // Register our string package with HII and return the handle to it.
  //
  gHiiHandle = HiiAddPackages (&gEfiCallerIdGuid, ImageHandle, DPStrings, NULL);
  ASSERT (gHiiHandle != NULL);

  // Initial the command list
  //
  InitialShellParamList ();
  
/****************************************************************************
****            Process Command Line arguments                           ****
****************************************************************************/
  Status = ShellCommandLineParse (DpParamList, &ParamPackage, NULL, TRUE);

  if (EFI_ERROR(Status)) {
    PrintToken (STRING_TOKEN (STR_DP_INVALID_ARG));
    ShowHelp();
  }
  else {
    StringDpOptionQh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_QH), NULL);
    StringDpOptionLh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LH), NULL);
    StringDpOptionUh = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UH), NULL);
    
    if (ShellCommandLineGetFlag (ParamPackage, StringDpOptionQh)  ||
        ShellCommandLineGetFlag (ParamPackage, StringDpOptionLh)  ||
        ShellCommandLineGetFlag (ParamPackage, StringDpOptionUh))
    {
      ShowHelp();
    }
    else {
      StringDpOptionLv = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LV), NULL);
      StringDpOptionUs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_US), NULL);
      StringDpOptionLs = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LS), NULL);
      StringDpOptionUa = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UA), NULL);
      StringDpOptionUr = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UR), NULL);
      StringDpOptionUt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UT), NULL);
      StringDpOptionUp = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_UP), NULL);
      StringDpOptionLx = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LX), NULL);
      StringDpOptionLn = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LN), NULL);
      StringDpOptionLt = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LT), NULL);
      StringDpOptionLi = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LI), NULL);
      StringDpOptionLc = HiiGetString (gHiiHandle, STRING_TOKEN (STR_DP_OPTION_LC), NULL);
      
      // Boolean Options
      // 
      VerboseMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLv);
      SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, StringDpOptionUs) ||
                    ShellCommandLineGetFlag (ParamPackage, StringDpOptionLs));
      AllMode     = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUa);
      RawMode     = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUr);
#if PROFILING_IMPLEMENTED
      TraceMode   = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUt);
      ProfileMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionUp);
#endif  // PROFILING_IMPLEMENTED
      ExcludeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLx);
      mShowId     =  ShellCommandLineGetFlag (ParamPackage, StringDpOptionLi);
      CumulativeMode = ShellCommandLineGetFlag (ParamPackage, StringDpOptionLc);

      // Options with Values
      CmdLineArg  = ShellCommandLineGetValue (ParamPackage, StringDpOptionLn);
      if (CmdLineArg == NULL) {
        Number2Display = DEFAULT_DISPLAYCOUNT;
      }
      else {
        Number2Display = StrDecimalToUintn(CmdLineArg);
        if (Number2Display == 0) {
          Number2Display = MAXIMUM_DISPLAYCOUNT;
        }
      }
      CmdLineArg  = ShellCommandLineGetValue (ParamPackage, StringDpOptionLt);
      if (CmdLineArg == NULL) {
        mInterestThreshold = DEFAULT_THRESHOLD;  // 1ms := 1,000 us
      }
      else {
        mInterestThreshold = StrDecimalToUint64(CmdLineArg);
      }
      // Handle Flag combinations and default behaviors
      // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
      if ((! TraceMode) && (! ProfileMode)) {
        TraceMode   = TRUE;
#if PROFILING_IMPLEMENTED
        ProfileMode = TRUE;
#endif  // PROFILING_IMPLEMENTED
      }

  //
  // Init the custom cumulative data.
  //
  CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, StringDpOptionLc);
  if (CustomCumulativeToken != NULL) {
    CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
    ASSERT (CustomCumulativeData != NULL);
    CustomCumulativeData->MinDur = 0;
    CustomCumulativeData->MaxDur = 0;
    CustomCumulativeData->Count  = 0;
    CustomCumulativeData->Duration = 0;
    CustomCumulativeData->Name   = AllocateZeroPool (StrLen (CustomCumulativeToken) + 1);
    UnicodeStrToAsciiStr (CustomCumulativeToken, CustomCumulativeData->Name);
  }

/****************************************************************************
****            Timer specific processing                                ****
****************************************************************************/
      // Get the Performance counter characteristics:
      //          Freq = Frequency in Hz
      //    StartCount = Value loaded into the counter when it starts counting
      //      EndCount = Value counter counts to before it needs to be reset
      //
      Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);

      // Convert the Frequency from Hz to KHz
      TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);

      // Determine in which direction the performance counter counts.
      TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);

/****************************************************************************
****            Print heading                                            ****
****************************************************************************/
      // print DP's build version
      PrintToken (STRING_TOKEN (STR_DP_BUILD_REVISION), DP_MAJOR_VERSION, DP_MINOR_VERSION);

      // print performance timer characteristics
      PrintToken (STRING_TOKEN (STR_DP_KHZ), TimerInfo.Frequency);         // Print Timer frequency in KHz

      if ((VerboseMode)   &&
          (! RawMode)
         ) {
        StringPtr = HiiGetString (gHiiHandle,
                      (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)),
                      NULL);
        ASSERT (StringPtr != NULL);
        PrintToken (STRING_TOKEN (STR_DP_TIMER_PROPERTIES),   // Print Timer count range and direction
                    StringPtr,
                    TimerInfo.StartCount,
                    TimerInfo.EndCount
                    );
        PrintToken (STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), mInterestThreshold);
      }

/* **************************************************************************
****            Print Sections based on command line options
****
****  Option modes have the following priority:
****    v Verbose     --  Valid in combination with any other options
****    t Threshold   --  Modifies All, Raw, and Cooked output
****                      Default is 0 for All and Raw mode
****                      Default is DEFAULT_THRESHOLD for "Cooked" mode
****    n Number2Display  Used by All and Raw mode.  Otherwise ignored.
****    A All         --  R and S options are ignored
****    R Raw         --  S option is ignored
****    s Summary     --  Modifies "Cooked" output only
****    Cooked (Default)
****
****  The All, Raw, and Cooked modes are modified by the Trace and Profile
****  options.
****    !T && !P  := (0) Default, Both are displayed
****     T && !P  := (1) Only Trace records are displayed
****    !T &&  P  := (2) Only Profile records are displayed
****     T &&  P  := (3) Same as Default, both are displayed
****************************************************************************/
      GatherStatistics (CustomCumulativeData);
      if (CumulativeMode) {                       
        ProcessCumulative (CustomCumulativeData);
      } else if (AllMode) {
        if (TraceMode) {
          Status = DumpAllTrace( Number2Display, ExcludeMode);
          if (Status == EFI_ABORTED) {
            goto Done;
          }
        }
        if (ProfileMode) {
          DumpAllProfile( Number2Display, ExcludeMode);
        }
      }
      else if (RawMode) {
        if (TraceMode) {
          Status = DumpRawTrace( Number2Display, ExcludeMode);
          if (Status == EFI_ABORTED) {
            goto Done;
          }
        }
        if (ProfileMode) {
          DumpRawProfile( Number2Display, ExcludeMode);
        }
      }
      else {
        //------------- Begin Cooked Mode Processing
        if (TraceMode) {
          ProcessPhases ( Ticker );
          if ( ! SummaryMode) {
            Status = ProcessHandles ( ExcludeMode);
            if (Status == EFI_ABORTED) {
              goto Done;
            }

            Status = ProcessPeims ();
            if (Status == EFI_ABORTED) {
              goto Done;
            }

            Status = ProcessGlobal ();
            if (Status == EFI_ABORTED) {
              goto Done;
            }

            ProcessCumulative (NULL);
          }
        }
        if (ProfileMode) {
          DumpAllProfile( Number2Display, ExcludeMode);
        }
      } //------------- End of Cooked Mode Processing
      if ( VerboseMode || SummaryMode) {
        DumpStatistics();
      }
    }
  }

Done:

  //
  // Free the memory allocate from HiiGetString
  //
  ListIndex = 0;
  while (DpParamList[ListIndex].Name != NULL) {
    FreePool (DpParamList[ListIndex].Name);
    ListIndex ++;
  }  
  FreePool (DpParamList);

  SafeFreePool (StringDpOptionQh);
  SafeFreePool (StringDpOptionLh);
  SafeFreePool (StringDpOptionUh);
  SafeFreePool (StringDpOptionLv);
  SafeFreePool (StringDpOptionUs);
  SafeFreePool (StringDpOptionLs);
  SafeFreePool (StringDpOptionUa);
  SafeFreePool (StringDpOptionUr);
  SafeFreePool (StringDpOptionUt);
  SafeFreePool (StringDpOptionUp);
  SafeFreePool (StringDpOptionLx);
  SafeFreePool (StringDpOptionLn);
  SafeFreePool (StringDpOptionLt);
  SafeFreePool (StringDpOptionLi);
  SafeFreePool (StringDpOptionLc);
  SafeFreePool (StringPtr);
  SafeFreePool (mPrintTokenBuffer);

  if (CustomCumulativeData != NULL) {
    SafeFreePool (CustomCumulativeData->Name);
  }
  SafeFreePool (CustomCumulativeData);

  HiiRemovePackages (gHiiHandle);
  return Status;
}
Example #9
0
/**
  Initialize the debug port.

  If Function is not NULL, Debug Communication Libary will call this function
  by passing in the Context to be the first parameter. If needed, Debug Communication
  Library will create one debug port handle to be the second argument passing in
  calling the Function, otherwise it will pass NULL to be the second argument of
  Function.

  If Function is NULL, and Context is not NULL, the Debug Communication Library could
    a) Return the same handle as passed in (as Context parameter).
    b) Ignore the input Context parameter and create new hanlde to be returned.

  If parameter Function is NULL and Context is NULL, Debug Communication Library could
  created a new handle if needed and return it, otherwise it will return NULL.

  @param[in] Context      Context needed by callback function; it was optional.
  @param[in] Function     Continue function called by Debug Communication library;
                          it was optional.

  @return  The debug port handle created by Debug Communication Library if Function
           is not NULL.

**/
DEBUG_PORT_HANDLE
EFIAPI
DebugPortInitialize (
  IN VOID                 *Context,
  IN DEBUG_PORT_CONTINUE  Function
  )
{
  RETURN_STATUS             Status;
  USB_DEBUG_PORT_HANDLE     Handle;
  USB_DEBUG_PORT_HANDLE     *UsbDebugPortHandle;
  UINT64                    TimerStartValue;
  UINT64                    TimerEndValue;

  //
  // Validate the PCD PcdDebugPortHandleBufferSize value 
  //
  ASSERT (PcdGet16 (PcdDebugPortHandleBufferSize) == sizeof (USB_DEBUG_PORT_HANDLE));

  if (Function == NULL && Context != NULL) {
    UsbDebugPortHandle = (USB_DEBUG_PORT_HANDLE *)Context;
  } else {
    ZeroMem(&Handle, sizeof (USB_DEBUG_PORT_HANDLE));
    UsbDebugPortHandle = &Handle;
  }

  UsbDebugPortHandle->TimerFrequency = GetPerformanceCounterProperties (
                                         &TimerStartValue,
                                         &TimerEndValue
                                         );
  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerFrequency  = 0x%lx\n", UsbDebugPortHandle->TimerFrequency)); 
  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerStartValue = 0x%lx\n", TimerStartValue)); 
  DEBUG ((EFI_D_INFO, "USB Debug Port: TimerEndValue   = 0x%lx\n", TimerEndValue)); 

  if (TimerEndValue < TimerStartValue) {
    UsbDebugPortHandle->TimerCountDown = TRUE;
    UsbDebugPortHandle->TimerCycle     = TimerStartValue - TimerEndValue;
  } else {
    UsbDebugPortHandle->TimerCountDown = FALSE;
    UsbDebugPortHandle->TimerCycle     = TimerEndValue - TimerStartValue;
  }   

  if (Function == NULL && Context != NULL) {
    return (DEBUG_PORT_HANDLE *) Context;
  }

  Status = CalculateUsbDebugPortBar(&Handle.DebugPortOffset, &Handle.DebugPortBarNumber);
  if (RETURN_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "UsbDbg: the pci device pointed by PcdUsbEhciPciAddress is not EHCI host controller or does not support debug port capability!\n"));
    goto Exit;
  }

  Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);

  if (Handle.EhciMemoryBase == 0) {
    //
    // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
    //
    PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET, PcdGet32(PcdUsbEhciMemorySpaceBase));
    Handle.EhciMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET);
  }

  Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);

  if (Handle.UsbDebugPortMemoryBase == 0) {
    //
    // Usb Debug Port MMIO Space Is Not Enabled. Assumption here that DebugPortBase is zero
    //
    PciWrite32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4, PcdGet32(PcdUsbDebugPortMemorySpaceBase));
    Handle.UsbDebugPortMemoryBase = 0xFFFFFC00 & PciRead32(PcdGet32(PcdUsbEhciPciAddress) + PCI_BASE_ADDRESSREG_OFFSET + Handle.DebugPortBarNumber * 4);
  }

  Handle.Initialized = USBDBG_RESET;

  if (NeedReinitializeHardware(&Handle)) {
    DEBUG ((EFI_D_ERROR, "UsbDbg: Start EHCI debug port initialization!\n"));
    Status = InitializeUsbDebugHardware (&Handle);
    if (RETURN_ERROR(Status)) {
      DEBUG ((EFI_D_ERROR, "UsbDbg: Failed, please check if USB debug cable is plugged into EHCI debug port correctly!\n"));
      goto Exit;
    }
  }

Exit:

  if (Function != NULL) {
    Function (Context, &Handle);
  } else {
    CopyMem(&mUsbDebugPortHandle, &Handle, sizeof (USB_DEBUG_PORT_HANDLE));
  }

  return (DEBUG_PORT_HANDLE)(UINTN)&mUsbDebugPortHandle;
Example #10
0
/**
  Simple arm disassembler via a library

  Argv[0] - disasm
  Argv[1] - Address to start disassembling from
  ARgv[2] - Number of instructions to disassembly (optional)

  @param  Argc   Number of command arguments in Argv
  @param  Argv   Array of strings that represent the parsed command line. 
                 Argv[0] is the command name

  @return EFI_SUCCESS

**/
EFI_STATUS
EblPerformance (
  IN UINTN  Argc,
  IN CHAR8  **Argv
  )
{
  UINTN       Key;
  CONST VOID  *Handle;
  CONST CHAR8 *Token, *Module;
  UINT64      Start, Stop, TimeStamp;
  UINT64      Delta, TicksPerSecond, Milliseconds, Microseconds;
  UINTN       Index;
  BOOLEAN     CountUp;

  TicksPerSecond = GetPerformanceCounterProperties (&Start, &Stop);
  if (Start < Stop) {
    CountUp = TRUE;
  } else {
    CountUp = FALSE;
  }

  Key       = 0;
  do {
    Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
    if (Key != 0) {
      if (AsciiStriCmp ("StartImage:", Token) == 0) {
        if (Stop == 0) {
          // The entry for EBL is still running so the stop time will be zero. Skip it
          AsciiPrint ("   running     %a\n", ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
        } else {
          Delta =  CountUp?(Stop - Start):(Start - Stop);
          Microseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000000), TicksPerSecond, NULL);
          AsciiPrint ("%10ld us  %a\n", Microseconds, ImageHandleToPdbFileName ((EFI_HANDLE)Handle));
        }
      }
    }
  } while (Key != 0);

  AsciiPrint ("\n");

  TimeStamp = 0;
  Key       = 0;
  do {
    Key = GetPerformanceMeasurement (Key, (CONST VOID **)&Handle, &Token, &Module, &Start, &Stop);
    if (Key != 0) {
      for (Index = 0; mTokenList[Index] != NULL; Index++) {
        if (AsciiStriCmp (mTokenList[Index], Token) == 0) {
          Delta =  CountUp?(Stop - Start):(Start - Stop);
          TimeStamp += Delta;
          Milliseconds = DivU64x64Remainder (MultU64x32 (Delta, 1000), TicksPerSecond, NULL);
          AsciiPrint ("%6a %6ld ms\n", Token, Milliseconds);
          break;
        }
      }   
    }
  } while (Key != 0);

  AsciiPrint ("Total Time = %ld ms\n\n", DivU64x64Remainder (MultU64x32 (TimeStamp, 1000), TicksPerSecond, NULL));

  return EFI_SUCCESS;
}
Example #11
0
/**
  This service enables the sending of commands to the TPM12.

  @param[in]     InputParameterBlockSize   Size of the TPM12 input parameter block.
  @param[in]     InputParameterBlock       Pointer to the TPM12 input parameter block.
  @param[in,out] OutputParameterBlockSize  Size of the TPM12 output parameter block.
  @param[in]     OutputParameterBlock      Pointer to the TPM12 output parameter block.

  @retval EFI_SUCCESS           The command byte stream was successfully sent to
                                the device and a response was successfully received.
  @retval EFI_DEVICE_ERROR      The command was not successfully sent to the
                                device or a response was not successfully received
                                from the device.
  @retval EFI_BUFFER_TOO_SMALL  The output parameter block is too small.
**/
EFI_STATUS
EFIAPI
Tpm12SubmitCommand (
  IN UINT32      InputParameterBlockSize,
  IN UINT8       *InputParameterBlock,
  IN OUT UINT32  *OutputParameterBlockSize,
  IN UINT8       *OutputParameterBlock
  )
{
  EFI_STATUS           Status;
  UINT32               TpmOutSize;
  TPM_RSP_COMMAND_HDR  *ResponseHeader;
  UINT64               Current;
  UINT64               Previous;
  UINT64               Total;
  UINT64               Start;
  UINT64               End;
  UINT64               Timeout;
  INT64                Cycle;
  INT64                Delta;

  //
  // Make sure response buffer is big enough to hold a response header
  //
  if (*OutputParameterBlockSize < sizeof (TPM_RSP_COMMAND_HDR)) {
    Status = EFI_BUFFER_TOO_SMALL;
    goto Done;
  }

  //
  // Get the current timer value
  //
  Current = GetPerformanceCounter();

  //
  // Initialize local variables
  //
  Start = 0;
  End   = 0;
  Total = 0;

  //
  // Retrieve the performance counter properties and compute the number of
  // performance counter ticks required to reach the maximum TIS timeout of
  // TIS_TIMEOUT_A.  TIS_TIMEOUT_A is in microseconds.
  //
  Timeout = DivU64x32 (
              MultU64x32 (
                GetPerformanceCounterProperties (&Start, &End),
                TIS_TIMEOUT_A
                ),
              1000000
              );
  Cycle = End - Start;
  if (Cycle < 0) {
    Cycle = -Cycle;
  }
  Cycle++;

  //
  // Send command
  //
  do {
    Status = WriteTpmBufferMultiple (InputParameterBlock, InputParameterBlockSize);

    Previous = Current;
    Current  = GetPerformanceCounter();
    Delta = (INT64) (Current - Previous);
    if (Start > End) {
      Delta = -Delta;
    }
    if (Delta < 0) {
      Delta += Cycle;
    }
    Total += Delta;
    if (Total >= Timeout) {
      Status = EFI_TIMEOUT;
      goto Done;
    }
  } while (EFI_ERROR (Status));

  //
  // Receive response header
  //
  do {
    Status = ReadTpmBufferMultiple (OutputParameterBlock, sizeof (TPM_RSP_COMMAND_HDR));

    Previous = Current;
    Current  = GetPerformanceCounter();
    Delta = (INT64) (Current - Previous);
    if (Start > End) {
      Delta = -Delta;
    }
    if (Delta < 0) {
      Delta += Cycle;
    }
    Total += Delta;
    if (Total >= Timeout) {
      Status = EFI_TIMEOUT;
      goto Done;
    }
  } while (EFI_ERROR (Status));

  //
  // Check the response data header (tag, parasize and returncode)
  //
  ResponseHeader = (TPM_RSP_COMMAND_HDR *)OutputParameterBlock;
  if (SwapBytes16 (ReadUnaligned16 (&ResponseHeader->tag)) != TPM_TAG_RSP_COMMAND) {
    Status = EFI_DEVICE_ERROR;
    goto Done;
  }

  TpmOutSize = SwapBytes32 (ReadUnaligned32 (&ResponseHeader->paramSize));
  if (TpmOutSize == sizeof (TPM_RSP_COMMAND_HDR)) {
    Status = EFI_SUCCESS;
    goto Done;
  }
  if (TpmOutSize < sizeof (TPM_RSP_COMMAND_HDR)) {
    Status = EFI_DEVICE_ERROR;
    goto Done;
  }
  if (*OutputParameterBlockSize < TpmOutSize) {
    Status = EFI_BUFFER_TOO_SMALL;
    goto Done;
  }
  *OutputParameterBlockSize = TpmOutSize;

  //
  // Receive the remaining data in the response header
  //
  do {
    Status = ReadTpmBufferMultiple (
               OutputParameterBlock + sizeof (TPM_RSP_COMMAND_HDR),
               TpmOutSize - sizeof (TPM_RSP_COMMAND_HDR)
               );

    Previous = Current;
    Current  = GetPerformanceCounter();
    Delta = (INT64) (Current - Previous);
    if (Start > End) {
      Delta = -Delta;
    }
    if (Delta < 0) {
      Delta += Cycle;
    }
    Total += Delta;
    if (Total >= Timeout) {
      Status = EFI_TIMEOUT;
      goto Done;
    }
  } while (EFI_ERROR (Status));

Done:
  DEBUG ((
    EFI_D_VERBOSE,
    "Tpm12SubmitCommand() Status = %r  Time = %ld ms\n",
    Status,
    DivU64x64Remainder (
      MultU64x32 (Total, 1000),
      GetPerformanceCounterProperties (NULL, NULL),
      NULL
      )
    ));

  return Status;
}
Example #12
0
/**
  This service requests use TPM12.

  @retval EFI_SUCCESS       Get the control of TPM12 chip.
  @retval EFI_NOT_FOUND     TPM12 not found.
  @retval EFI_DEVICE_ERROR  Unexpected device behavior.
**/
EFI_STATUS
EFIAPI
Tpm12RequestUseTpm (
  VOID
  )
{
  EFI_STATUS                 Status;
  UINT8                      Data;
  UINT64                     Current;
  UINT64                     Previous;
  UINT64                     Total;
  UINT64                     Start;
  UINT64                     End;
  UINT64                     Timeout;
  INT64                      Cycle;
  INT64                      Delta;

  //
  // Get the current timer value
  //
  Current = GetPerformanceCounter();

  //
  // Initialize local variables
  //
  Start = 0;
  End   = 0;
  Total = 0;

  //
  // Retrieve the performance counter properties and compute the number of
  // performance counter ticks required to reach the maximum TIS timeout of
  // TIS_TIMEOUT_A.  TIS_TIMEOUT_A is in microseconds.
  //
  Timeout = DivU64x32 (
              MultU64x32 (
                GetPerformanceCounterProperties (&Start, &End),
                TIS_TIMEOUT_A
                ),
              1000000
              );
  Cycle = End - Start;
  if (Cycle < 0) {
    Cycle = -Cycle;
  }
  Cycle++;

  //
  // Attempt to read a byte from the Atmel I2C TPM
  //
  do {
    Status = ReadTpmBufferMultiple (&Data, sizeof(Data));

    Previous = Current;
    Current  = GetPerformanceCounter();
    Delta = (INT64) (Current - Previous);
    if (Start > End) {
      Delta = -Delta;
    }
    if (Delta < 0) {
      Delta += Cycle;
    }
    Total += Delta;
    if (Total >= Timeout) {
      Status = EFI_TIMEOUT;
      DEBUG ((EFI_D_ERROR, "Atmel I2C TPM failed to read: %r\n", Status));
      return Status;
    }
  } while (EFI_ERROR (Status));

  //
  // Send Physical Presence Command to Atmel I2C TPM
  //
  Status = Tpm12PhysicalPresence (TPM_PHYSICAL_PRESENCE_PRESENT);
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Atmel I2C TPM failed to submit physical presence command: %r\n", Status));
    return Status;
  }

  return EFI_SUCCESS;
}
Example #13
0
/**
  Performance measure function to get S3 detailed performance data.

  This function will getS3 detailed performance data and saved in pre-reserved ACPI memory.
**/
VOID
WriteToOsS3PerformanceData (
  VOID
  )
{
  EFI_STATUS                                    Status;
  EFI_PHYSICAL_ADDRESS                          mAcpiLowMemoryBase;
  PERF_HEADER                                   *PerfHeader;
  PERF_DATA                                     *PerfData;
  UINT64                                        Ticker;
  UINTN                                         Index;
  EFI_PEI_READ_ONLY_VARIABLE2_PPI               *VariableServices;
  UINTN                                         VarSize;
  UINTN                                         LogEntryKey;
  CONST VOID                                    *Handle;
  CONST CHAR8                                   *Token;
  CONST CHAR8                                   *Module;
  UINT64                                        StartTicker;
  UINT64                                        EndTicker;
  UINT64                                        StartValue;
  UINT64                                        EndValue;
  BOOLEAN                                       CountUp;
  UINT64                                        Freq;

  //
  // Retrive time stamp count as early as possilbe
  //
  Ticker = GetPerformanceCounter ();

  Freq   = GetPerformanceCounterProperties (&StartValue, &EndValue);

  Freq   = DivU64x32 (Freq, 1000);

  Status = PeiServicesLocatePpi (
             &gEfiPeiReadOnlyVariable2PpiGuid,
             0,
             NULL,
             (VOID **) &VariableServices
             );
  ASSERT_EFI_ERROR (Status);

  VarSize   = sizeof (EFI_PHYSICAL_ADDRESS);
  Status = VariableServices->GetVariable (
                               VariableServices,
                               L"PerfDataMemAddr",
                               &gPerformanceProtocolGuid,
                               NULL,
                               &VarSize,
                               &mAcpiLowMemoryBase
                               );
  if (EFI_ERROR (Status)) {
    DEBUG ((EFI_D_ERROR, "Fail to retrieve variable to log S3 performance data \n"));
    return;
  }

  PerfHeader = (PERF_HEADER *) (UINTN) mAcpiLowMemoryBase;

  if (PerfHeader->Signiture != PERFORMANCE_SIGNATURE) {
    DEBUG ((EFI_D_ERROR, "Performance data in ACPI memory get corrupted! \n"));
    return;
  }

  //
  // Record total S3 resume time.
  //
  if (EndValue >= StartValue) {
    PerfHeader->S3Resume = Ticker - StartValue;
    CountUp              = TRUE;
  } else {
    PerfHeader->S3Resume = StartValue - Ticker;
    CountUp              = FALSE;
  }

  //
  // Get S3 detailed performance data
  //
  Index = 0;
  LogEntryKey = 0;
  while ((LogEntryKey = GetPerformanceMeasurement (
                          LogEntryKey,
                          &Handle,
                          &Token,
                          &Module,
                          &StartTicker,
                          &EndTicker)) != 0) {
    if (EndTicker != 0) {
      PerfData = &PerfHeader->S3Entry[Index];

      //
      // Use File Handle to specify the different performance log for PEIM.
      // File Handle is the base address of PEIM FFS file.
      //
      if ((AsciiStrnCmp (Token, "PEIM", PEI_PERFORMANCE_STRING_SIZE) == 0) && (Handle != NULL)) {
        AsciiSPrint (PerfData->Token, PERF_TOKEN_LENGTH, "0x%11p", Handle);
      } else {
        AsciiStrnCpy (PerfData->Token, Token, PERF_TOKEN_LENGTH);
      }
      if (StartTicker == 1) {
        StartTicker = StartValue;
      }
      if (EndTicker == 1) {
        EndTicker = StartValue;
      }
      Ticker = CountUp? (EndTicker - StartTicker) : (StartTicker - EndTicker);
      PerfData->Duration = (UINT32) DivU64x32 (Ticker, (UINT32) Freq);

      //
      // Only Record > 1ms performance data so that more big performance can be recorded.
      //
      if ((Ticker > Freq) && (++Index >= PERF_PEI_ENTRY_MAX_NUM)) {
        //
        // Reach the maximum number of PEI performance log entries.
        //
        break;
      }
    }
  }
  PerfHeader->S3EntryNum = (UINT32) Index;
}