Esempio n. 1
0
/**
  Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
  performance data for ExitBootServicesEntry in FPDT.

  @param[in]  Event   The Event that is being processed.
  @param[in]  Context The Event Context.

**/
VOID
EFIAPI
FpdtExitBootServicesEventNotify (
  IN EFI_EVENT        Event,
  IN VOID             *Context
  )
{
  if (mAcpiBootPerformanceTable == NULL) {
    //
    // Firmware Performance Data Table not installed, do nothing.
    //
    return ;
  }

  //
  // Update Firmware Basic Boot Performance Record for UEFI boot.
  //
  mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());

  //
  // Dump FPDT Boot Performance record.
  //
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd                = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart  = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry   = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));
  //
  // ExitBootServicesExit will be updated later, so don't dump it here.
  //
}
/**
  Notify function for event EVT_SIGNAL_EXIT_BOOT_SERVICES. This is used to record
  performance data for ExitBootServicesEntry in FPDT.

  @param[in]  Event   The Event that is being processed.
  @param[in]  Context The Event Context.

**/
VOID
EFIAPI
FpdtExitBootServicesEventNotify (
  IN EFI_EVENT        Event,
  IN VOID             *Context
  )
{
  if (!mDxeCoreReportStatusCodeEnable) {
    //
    // When DxeCore Report Status Code is disabled, 
    // Unregister boot time report status code listener at ExitBootService Event.
    //
    mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);
  }

  if (mAcpiBootPerformanceTable == NULL) {
    //
    // Firmware Performance Data Table not installed, do nothing.
    //
    return ;
  }

  //
  // Update Firmware Basic Boot Performance Record for UEFI boot.
  //
  mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry = GetTimeInNanoSecond (GetPerformanceCounter ());

  //
  // Dump FPDT Boot Performance record.
  //
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ResetEnd                = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ResetEnd));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderLoadImageStart  = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - OsLoaderStartImageStart = %ld\n", mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart));
  DEBUG ((EFI_D_INFO, "FPDT: Boot Performance - ExitBootServicesEntry   = %ld\n", mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesEntry));
  //
  // ExitBootServicesExit will be updated later, so don't dump it here.
  //
}
/**
  Report status code listener for SMM. This is used to record the performance
  data for S3 Suspend Start and S3 Suspend End in FPDT.

  @param[in]  CodeType            Indicates the type of status code being reported.
  @param[in]  Value               Describes the current status of a hardware or software entity.
                                  This included information about the class and subclass that is used to
                                  classify the entity as well as an operation.
  @param[in]  Instance            The enumeration of a hardware or software entity within
                                  the system. Valid instance numbers start with 1.
  @param[in]  CallerId            This optional parameter may be used to identify the caller.
                                  This parameter allows the status code driver to apply different rules to
                                  different callers.
  @param[in]  Data                This optional parameter may be used to pass additional data.

  @retval EFI_SUCCESS             Status code is what we expected.
  @retval EFI_UNSUPPORTED         Status code not supported.

**/
EFI_STATUS
EFIAPI
FpdtStatusCodeListenerSmm (
  IN EFI_STATUS_CODE_TYPE     CodeType,
  IN EFI_STATUS_CODE_VALUE    Value,
  IN UINT32                   Instance,
  IN EFI_GUID                 *CallerId,
  IN EFI_STATUS_CODE_DATA     *Data
  )
{
  EFI_STATUS                           Status;
  UINT64                               CurrentTime;
  EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD  S3SuspendRecord;
  UINT8                                *NewRecordBuffer;

  //
  // Check whether status code is what we are interested in.
  //
  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {
    return EFI_UNSUPPORTED;
  }
  
  //
  // Collect one or more Boot records in boot time
  //
  if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
    AcquireSpinLock (&mSmmFpdtLock);
    
    if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
      //
      // Try to allocate big SMRAM data to store Boot record. 
      //
      if (mSmramIsOutOfResource) {
        ReleaseSpinLock (&mSmmFpdtLock);
        return EFI_OUT_OF_RESOURCES;
      }
      NewRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer); 
      if (NewRecordBuffer == NULL) {
        ReleaseSpinLock (&mSmmFpdtLock);
        mSmramIsOutOfResource = TRUE;
        return EFI_OUT_OF_RESOURCES;
      }
      mBootRecordBuffer  = NewRecordBuffer;
      mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE;
    }
    //
    // Save boot record into the temp memory space.
    //
    CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
    mBootRecordSize += Data->Size;
    
    ReleaseSpinLock (&mSmmFpdtLock);
    return EFI_SUCCESS;
  }

  if ((Value != PcdGet32 (PcdProgressCodeS3SuspendStart)) &&
      (Value != PcdGet32 (PcdProgressCodeS3SuspendEnd))) {
    return EFI_UNSUPPORTED;
  }

  //
  // Retrieve current time.
  //
  CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());

  if (Value == PcdGet32 (PcdProgressCodeS3SuspendStart)) {
    //
    // S3 Suspend started, record the performance data and return.
    //
    mSuspendStartTime = CurrentTime;
    return EFI_SUCCESS;
  }

  //
  // We are going to S3 sleep, record S3 Suspend End performance data.
  //
  S3SuspendRecord.SuspendStart = mSuspendStartTime;
  S3SuspendRecord.SuspendEnd   = CurrentTime;

  //
  // Save S3 suspend performance data to lock box, it will be used by Firmware Performance PEIM.
  //
  if (!mS3SuspendLockBoxSaved) {
    Status = SaveLockBox (
               &gEfiFirmwarePerformanceGuid,
               &S3SuspendRecord,
               sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD)
               );
    ASSERT_EFI_ERROR (Status);

    mS3SuspendLockBoxSaved = TRUE;
  } else {
    Status = UpdateLockBox (
               &gEfiFirmwarePerformanceGuid,
               0,
               &S3SuspendRecord,
               sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD)
               );
    ASSERT_EFI_ERROR (Status);
  }

  return EFI_SUCCESS;
}
Esempio n. 4
0
/**
  Report status code listener of FPDT. This is used to collect performance data
  for OsLoaderLoadImageStart and OsLoaderStartImageStart in FPDT.

  @param[in]  CodeType            Indicates the type of status code being reported.
  @param[in]  Value               Describes the current status of a hardware or software entity.
                                  This included information about the class and subclass that is used to
                                  classify the entity as well as an operation.
  @param[in]  Instance            The enumeration of a hardware or software entity within
                                  the system. Valid instance numbers start with 1.
  @param[in]  CallerId            This optional parameter may be used to identify the caller.
                                  This parameter allows the status code driver to apply different rules to
                                  different callers.
  @param[in]  Data                This optional parameter may be used to pass additional data.

  @retval EFI_SUCCESS             Status code is what we expected.
  @retval EFI_UNSUPPORTED         Status code not supported.

**/
EFI_STATUS
EFIAPI
FpdtStatusCodeListenerDxe (
  IN EFI_STATUS_CODE_TYPE     CodeType,
  IN EFI_STATUS_CODE_VALUE    Value,
  IN UINT32                   Instance,
  IN EFI_GUID                 *CallerId,
  IN EFI_STATUS_CODE_DATA     *Data
  )
{
  EFI_STATUS  Status;

  //
  // Check whether status code is what we are interested in.
  //
  if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) {
    return EFI_UNSUPPORTED;
  }

  Status = EFI_SUCCESS;
  if (Value == PcdGet32 (PcdProgressCodeOsLoaderLoad)) {
    //
    // Progress code for OS Loader LoadImage.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update OS Loader LoadImage Start for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.OsLoaderLoadImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
  } else if (Value == PcdGet32 (PcdProgressCodeOsLoaderStart)) {
    //
    // Progress code for OS Loader StartImage.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update OS Loader StartImage Start for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.OsLoaderStartImageStart = GetTimeInNanoSecond (GetPerformanceCounter ());
  } else if (Value == (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)) {
    //
    // Progress code for ExitBootServices.
    //
    if (mAcpiBootPerformanceTable == NULL) {
      return Status;
    }

    //
    // Update ExitBootServicesExit for UEFI boot.
    //
    mAcpiBootPerformanceTable->BasicBoot.ExitBootServicesExit = GetTimeInNanoSecond (GetPerformanceCounter ());

    //
    // Unregister boot time report status code listener.
    //
    mRscHandlerProtocol->Unregister (FpdtStatusCodeListenerDxe);
  } else if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) {
    //
    // Append one or more Boot records
    //
    if (mAcpiBootPerformanceTable == NULL) {
      //
      // Append Boot records before FPDT ACPI table is installed. 
      //
      if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
        mBootRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer);
        ASSERT (mBootRecordBuffer != NULL);
        mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE;
      }
      //
      // Save boot record into the temp memory space.
      //
      CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
      mBootRecordSize += Data->Size;
    } else {
      //
      // Append Boot records after FPDT ACPI table is installed. 
      //
      if (mBootRecordSize + Data->Size > mBootRecordMaxSize) {
        //
        // No enough space to save boot record.
        //
        Status = EFI_OUT_OF_RESOURCES;
      } else {
        //
        // Save boot record into BootPerformance table
        //
        CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size);
        mBootRecordSize += Data->Size;
        mAcpiBootPerformanceTable->Header.Length = mBootRecordSize;
      }
    }
  } else {
    //
    // Ignore else progress code.
    //
    Status = EFI_UNSUPPORTED;
  }

  return Status;
}
/**
  Report status code listener for PEI. This is used to record the performance
  data for S3 FullResume in FPDT.

  @param[in]  PeiServices         An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation.
  @param[in]  CodeType            Indicates the type of status code being reported.
  @param[in]  Value               Describes the current status of a hardware or software entity.
                                  This included information about the class and subclass that is used to
                                  classify the entity as well as an operation.
  @param[in]  Instance            The enumeration of a hardware or software entity within
                                  the system. Valid instance numbers start with 1.
  @param[in]  CallerId            This optional parameter may be used to identify the caller.
                                  This parameter allows the status code driver to apply different rules to
                                  different callers.
  @param[in]  Data                This optional parameter may be used to pass additional data.

  @retval EFI_SUCCESS             Status code is what we expected.
  @retval EFI_UNSUPPORTED         Status code not supported.

**/
EFI_STATUS
EFIAPI
FpdtStatusCodeListenerPei (
  IN CONST  EFI_PEI_SERVICES        **PeiServices,
  IN        EFI_STATUS_CODE_TYPE    CodeType,
  IN        EFI_STATUS_CODE_VALUE   Value,
  IN        UINT32                  Instance,
  IN CONST  EFI_GUID                *CallerId,
  IN CONST  EFI_STATUS_CODE_DATA    *Data
  )
{
  EFI_STATUS                           Status;
  UINT64                               CurrentTime;
  EFI_PEI_READ_ONLY_VARIABLE2_PPI      *VariableServices;
  UINTN                                VarSize;
  FIRMWARE_PERFORMANCE_VARIABLE        PerformanceVariable;
  S3_PERFORMANCE_TABLE                 *AcpiS3PerformanceTable;
  EFI_ACPI_5_0_FPDT_S3_RESUME_RECORD   *AcpiS3ResumeRecord;
  UINT64                               S3ResumeTotal;
  EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD  S3SuspendRecord;
  EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD  *AcpiS3SuspendRecord;

  //
  // Check whether status code is what we are interested in.
  //
  if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) ||
  	  (Value != (EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_PC_OS_WAKE))) {
    return EFI_UNSUPPORTED;
  }

  //
  // Retrieve current time as early as possible.
  //
  CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ());

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

  //
  // Update S3 Resume Performance Record.
  //
  VarSize = sizeof (FIRMWARE_PERFORMANCE_VARIABLE);
  Status = VariableServices->GetVariable (
                               VariableServices,
                               EFI_FIRMWARE_PERFORMANCE_VARIABLE_NAME,
                               &gEfiFirmwarePerformanceGuid,
                               NULL,
                               &VarSize,
                               &PerformanceVariable
                               );
  if (EFI_ERROR (Status)) {
    return Status;
  }

  AcpiS3PerformanceTable = (S3_PERFORMANCE_TABLE *) (UINTN) PerformanceVariable.S3PerformanceTablePointer;
  ASSERT (AcpiS3PerformanceTable != NULL);
  ASSERT (AcpiS3PerformanceTable->Header.Signature == EFI_ACPI_5_0_FPDT_S3_PERFORMANCE_TABLE_SIGNATURE);
  AcpiS3ResumeRecord = &AcpiS3PerformanceTable->S3Resume;
  AcpiS3ResumeRecord->FullResume = CurrentTime;
  //
  // Calculate average S3 resume time.
  //
  S3ResumeTotal = MultU64x32 (AcpiS3ResumeRecord->AverageResume, AcpiS3ResumeRecord->ResumeCount);
  AcpiS3ResumeRecord->ResumeCount++;
  AcpiS3ResumeRecord->AverageResume = DivU64x32 (S3ResumeTotal + AcpiS3ResumeRecord->FullResume, AcpiS3ResumeRecord->ResumeCount);

  DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - ResumeCount   = %d\n", AcpiS3ResumeRecord->ResumeCount));
  DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - FullResume    = %ld\n", AcpiS3ResumeRecord->FullResume));
  DEBUG ((EFI_D_INFO, "FPDT: S3 Resume Performance - AverageResume = %ld\n", AcpiS3ResumeRecord->AverageResume));

  //
  // Update S3 Suspend Performance Record.
  //
  AcpiS3SuspendRecord = &AcpiS3PerformanceTable->S3Suspend;
  VarSize = sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD);
  ZeroMem (&S3SuspendRecord, sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD));
  Status = RestoreLockBox (
             &gEfiFirmwarePerformanceGuid,
             &S3SuspendRecord,
             &VarSize
             );
  ASSERT_EFI_ERROR (Status);

  AcpiS3SuspendRecord->SuspendStart = S3SuspendRecord.SuspendStart;
  AcpiS3SuspendRecord->SuspendEnd   = S3SuspendRecord.SuspendEnd;

  DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendStart = %ld\n", AcpiS3SuspendRecord->SuspendStart));
  DEBUG ((EFI_D_INFO, "FPDT: S3 Suspend Performance - SuspendEnd   = %ld\n", AcpiS3SuspendRecord->SuspendEnd));

  return EFI_SUCCESS;
}
Esempio n. 6
0
/**
  Convert PEI performance log to FPDT String boot record.

  @param  IsStart                 TRUE if the performance log is start log.
  @param  Handle                  Pointer to environment specific context used
                                  to identify the component being measured.
  @param  Token                   Pointer to a Null-terminated ASCII string
                                  that identifies the component being measured.
  @param  Module                  Pointer to a Null-terminated ASCII string
                                  that identifies the module being measured.
  @param  Ticker                  64-bit time stamp.
  @param  Identifier              32-bit identifier. If the value is 0, the created record
                                  is same as the one created by StartGauge of PERFORMANCE_PROTOCOL.

  @retval EFI_SUCCESS              Add FPDT boot record.
  @retval EFI_OUT_OF_RESOURCES     There are not enough resources to record the measurement.
  @retval EFI_UNSUPPORTED          No matched FPDT record.

**/
EFI_STATUS
InsertPeiFpdtMeasurement (
  IN BOOLEAN      IsStart,
  IN CONST VOID   *Handle,  OPTIONAL
  IN CONST CHAR8  *Token,   OPTIONAL
  IN CONST CHAR8  *Module,  OPTIONAL
  IN UINT64       Ticker,
  IN UINT32       Identifier
  )
{
  EFI_HOB_GUID_TYPE                     *GuidHob;
  UINTN                                 PeiPerformanceSize;
  UINT8                                 *PeiFirmwarePerformance;
  FPDT_PEI_EXT_PERF_HEADER              *PeiPerformanceLogHeader;
  FPDT_RECORD_PTR                       FpdtRecordPtr;
  FPDT_BASIC_RECORD_INFO                RecordInfo;
  CONST VOID                            *ModuleGuid;
  UINTN                                 DestMax;
  UINTN                                 StrLength;
  CONST CHAR8                           *StringPtr;
  EFI_STATUS                            Status;
  UINT16                                PeiPerformanceLogEntries;
  UINT64                                TimeStamp;

  StringPtr = NULL;
  FpdtRecordPtr.RecordHeader = NULL;
  PeiPerformanceLogHeader = NULL;

  //
  // Get record info (type, size, ProgressID and Module Guid).
  //
  Status = GetFpdtRecordInfo (IsStart, Handle, Token, Module, &RecordInfo);
  if (EFI_ERROR (Status)) {
    return Status;
  }

  //
  // If PERF_START()/PERF_END() have specified the ProgressID,it has high priority.
  // !!! Note: If the Perf is not the known Token used in the core but have same
  // ID with the core Token, this case will not be supported.
  // And in currtnt usage mode, for the unkown ID, there is a general rule:
  // If it is start pref: the lower 4 bits of the ID should be 0.
  // If it is end pref: the lower 4 bits of the ID should not be 0.
  // If input ID doesn't follow the rule, we will adjust it.
  //
  if ((Identifier != 0) && (IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
    return EFI_UNSUPPORTED;
  } else if ((Identifier != 0) && (!IsKnownID (Identifier)) && (!IsKnownTokens (Token))) {
    if (IsStart && ((Identifier & 0x000F) != 0)) {
      Identifier &= 0xFFF0;
    } else if ((!IsStart) && ((Identifier & 0x000F) == 0)) {
      Identifier += 1;
    }
    RecordInfo.ProgressID = (UINT16)Identifier;
  }

  //
  // Get the number of PeiPerformanceLogEntries form PCD.
  //
  PeiPerformanceLogEntries = (UINT16) (PcdGet16 (PcdMaxPeiPerformanceLogEntries16) != 0 ?
                                       PcdGet16 (PcdMaxPeiPerformanceLogEntries16) :
                                       PcdGet8 (PcdMaxPeiPerformanceLogEntries));

  //
  // Create GUID HOB Data.
  //
  GuidHob = GetFirstGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid);
  PeiFirmwarePerformance = NULL;
  while (GuidHob != NULL) {
    //
    // PEI Performance HOB was found, then return the existing one.
    //
    PeiFirmwarePerformance  = (UINT8*)GET_GUID_HOB_DATA (GuidHob);
    PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
    if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize > PeiPerformanceLogEntries * MAX_RECORD_SIZE) {
      PeiPerformanceLogHeader->HobIsFull = TRUE;
    }
    if (!PeiPerformanceLogHeader->HobIsFull && PeiPerformanceLogHeader->SizeOfAllEntries + RecordInfo.RecordSize <= PeiPerformanceLogEntries * MAX_RECORD_SIZE) {
      FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER) + PeiPerformanceLogHeader->SizeOfAllEntries);
      break;
    }
    //
    // Previous HOB is used, then find next one.
    //
    GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
  }

  if (GuidHob == NULL) {
    //
    // PEI Performance HOB was not found, then build one.
    //
    PeiPerformanceSize      = sizeof (FPDT_PEI_EXT_PERF_HEADER) +
                              MAX_RECORD_SIZE * PeiPerformanceLogEntries;
    PeiFirmwarePerformance  = (UINT8*)BuildGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, PeiPerformanceSize);
    if (PeiFirmwarePerformance != NULL) {
      ZeroMem (PeiFirmwarePerformance, PeiPerformanceSize);
    }
    PeiPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)PeiFirmwarePerformance;
    FpdtRecordPtr.RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(PeiFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));
  }

  if (PeiFirmwarePerformance == NULL) {
    //
    // there is no enough resource to store performance data
    //
    return EFI_OUT_OF_RESOURCES;
  }

  //
  // Get the TimeStamp.
  //
  if (Ticker == 0) {
    Ticker    = GetPerformanceCounter ();
    TimeStamp = GetTimeInNanoSecond (Ticker);
  } else if (Ticker == 1) {
    TimeStamp = 0;
  } else {
    TimeStamp = GetTimeInNanoSecond (Ticker);
  }

  //
  // Get the ModuleGuid.
  //
  if (Handle != NULL) {
    ModuleGuid = Handle;
  } else {
    ModuleGuid = &gEfiCallerIdGuid;
  }

  switch (RecordInfo.Type) {
  case FPDT_GUID_EVENT_TYPE:
    FpdtRecordPtr.GuidEvent->Header.Type       = FPDT_GUID_EVENT_TYPE;
    FpdtRecordPtr.GuidEvent->Header.Length     = RecordInfo.RecordSize;;
    FpdtRecordPtr.GuidEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
    FpdtRecordPtr.GuidEvent->ProgressID        = RecordInfo.ProgressID;
    FpdtRecordPtr.GuidEvent->Timestamp         = TimeStamp;
    CopyMem (&FpdtRecordPtr.GuidEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
    PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
    break;

  case FPDT_GUID_QWORD_EVENT_TYPE:
    FpdtRecordPtr.GuidQwordEvent->Header.Type     = FPDT_GUID_QWORD_EVENT_TYPE;
    FpdtRecordPtr.GuidQwordEvent->Header.Length   = RecordInfo.RecordSize;;
    FpdtRecordPtr.GuidQwordEvent->Header.Revision = FPDT_RECORD_REVISION_1;
    FpdtRecordPtr.GuidQwordEvent->ProgressID      = RecordInfo.ProgressID;
    FpdtRecordPtr.GuidQwordEvent->Timestamp       = TimeStamp;
    PeiPerformanceLogHeader->LoadImageCount++;
    FpdtRecordPtr.GuidQwordEvent->Qword           = PeiPerformanceLogHeader->LoadImageCount;
    CopyMem (&FpdtRecordPtr.GuidQwordEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
    PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;
    break;

  case FPDT_DYNAMIC_STRING_EVENT_TYPE:
    FpdtRecordPtr.DynamicStringEvent->Header.Type       = FPDT_DYNAMIC_STRING_EVENT_TYPE;
    FpdtRecordPtr.DynamicStringEvent->Header.Length     = RecordInfo.RecordSize;
    FpdtRecordPtr.DynamicStringEvent->Header.Revision   = FPDT_RECORD_REVISION_1;
    FpdtRecordPtr.DynamicStringEvent->ProgressID        = RecordInfo.ProgressID;
    FpdtRecordPtr.DynamicStringEvent->Timestamp         = TimeStamp;
    CopyMem (&FpdtRecordPtr.DynamicStringEvent->Guid, ModuleGuid, sizeof (EFI_GUID));
    PeiPerformanceLogHeader->SizeOfAllEntries += RecordInfo.RecordSize;

    if (Token != NULL) {
      StringPtr                     = Token;
    } else if (Module != NULL) {
      StringPtr                     = Module;
    }
    if (StringPtr != NULL && AsciiStrLen (StringPtr) != 0) {
      DestMax                       = (RecordInfo.RecordSize - sizeof (FPDT_DYNAMIC_STRING_EVENT_RECORD)) / sizeof (CHAR8);
      StrLength                     = AsciiStrLen (StringPtr);
      if (StrLength >= DestMax) {
        StrLength                   = DestMax -1;
      }
      AsciiStrnCpyS (FpdtRecordPtr.DynamicStringEvent->String, DestMax, StringPtr, StrLength);
    } else {
      AsciiStrCpyS (FpdtRecordPtr.DynamicStringEvent->String, FPDT_STRING_EVENT_RECORD_NAME_LENGTH, "unknown name");
    }
    break;

  default:
    //
    // Record is not supported in current PEI phase, return EFI_ABORTED
    //
    return EFI_UNSUPPORTED;
  }

  return EFI_SUCCESS;
}
Esempio n. 7
0
/**
This function is called after PEI core discover memory and finish migration.

@param[in] PeiServices    Pointer to PEI Services Table.
@param[in] NotifyDesc     Pointer to the descriptor for the Notification event that
caused this function to execute.
@param[in] Ppi            Pointer to the PPI data associated with this function.

@retval EFI_STATUS        Always return EFI_SUCCESS
**/
EFI_STATUS
EFIAPI
PeiMemoryDiscoveredNotify (
  IN EFI_PEI_SERVICES          **PeiServices,
  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
  IN VOID                      *Ppi
  )
{
  FSP_INFO_HEADER           *FspsHeaderPtr;
  UINT64                    TimeStampCounterStart;
  EFI_STATUS                Status;
  VOID                      *FspHobListPtr;
  EFI_HOB_GUID_TYPE         *GuidHob;
  FSPS_UPD_COMMON           *FspsUpdDataPtr;
  UINTN                     *SourceData;

  
  DEBUG ((DEBUG_INFO, "PeiMemoryDiscoveredNotify enter\n"));
  
  //
  // Copy default FSP-S UPD data from Flash
  //
  FspsHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspsBaseAddress));
  DEBUG ((DEBUG_INFO, "FspsHeaderPtr - 0x%x\n", FspsHeaderPtr));
  if (FspsHeaderPtr == NULL) {
    return EFI_DEVICE_ERROR;
  }

  FspsUpdDataPtr = (FSPS_UPD_COMMON *)AllocateZeroPool ((UINTN)FspsHeaderPtr->CfgRegionSize);
  ASSERT (FspsUpdDataPtr != NULL);
  SourceData = (UINTN *)((UINTN)FspsHeaderPtr->ImageBase + (UINTN)FspsHeaderPtr->CfgRegionOffset);
  CopyMem (FspsUpdDataPtr, SourceData, (UINTN)FspsHeaderPtr->CfgRegionSize);

  UpdateFspsUpdData ((VOID *)FspsUpdDataPtr);

  TimeStampCounterStart = AsmReadTsc ();
  PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x9000);
  Status = CallFspSiliconInit ((VOID *)FspsUpdDataPtr);
  PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0x907F);
  DEBUG ((DEBUG_INFO, "Total time spent executing FspSiliconInitApi: %d millisecond\n", DivU64x32 (GetTimeInNanoSecond (AsmReadTsc () - TimeStampCounterStart), 1000000)));

  //
  // Reset the system if FSP API returned FSP_STATUS_RESET_REQUIRED status
  //
  if ((Status >= FSP_STATUS_RESET_REQUIRED_COLD) && (Status <= FSP_STATUS_RESET_REQUIRED_8)) {
    DEBUG((DEBUG_INFO, "FspSiliconInitApi requested reset 0x%x\n", Status));
    CallFspWrapperResetSystem ((UINT32)Status);
  }

  if (EFI_ERROR(Status)) {
    DEBUG ((DEBUG_ERROR, "ERROR - Failed to execute FspSiliconInitApi(), Status = %r\n", Status));
  }
  DEBUG((DEBUG_INFO, "FspSiliconInit status: 0x%x\n", Status));
  ASSERT_EFI_ERROR (Status);

  Status = TestFspSiliconInitApiOutput ((VOID *)NULL);
  if (RETURN_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "ERROR - TestFspSiliconInitApiOutput () fail, Status = %r\n", Status));
  }

  //
  // Now FspHobList complete, process it
  //
  GuidHob = GetFirstGuidHob (&gFspHobGuid);
  ASSERT (GuidHob != NULL);
  FspHobListPtr = *(VOID **)GET_GUID_HOB_DATA (GuidHob);
  DEBUG ((DEBUG_INFO, "FspHobListPtr - 0x%x\n", FspHobListPtr));
  PostFspsHobProcess (FspHobListPtr);

  //
  // Install FspSiliconInitDonePpi so that any other driver can consume this info.
  //
  Status = PeiServicesInstallPpi (&mPeiFspSiliconInitDonePpi);
  ASSERT_EFI_ERROR(Status);

  return Status;
}
Esempio n. 8
0
/**
  Call FspMemoryInit API.

  @return Status returned by FspMemoryInit API.
**/
EFI_STATUS
PeiFspMemoryInit (
  VOID
  )
{
  FSP_INFO_HEADER           *FspmHeaderPtr;
  EFI_STATUS                Status;
  UINT64                    TimeStampCounterStart;
  VOID                      *FspHobListPtr;
  VOID                      *HobData;
  FSPM_UPD_COMMON           *FspmUpdDataPtr;
  UINTN                     *SourceData;

  DEBUG ((DEBUG_INFO, "PeiFspMemoryInit enter\n"));

  FspHobListPtr = NULL;

  //
  // Copy default FSP-M UPD data from Flash
  //
  FspmHeaderPtr = (FSP_INFO_HEADER *)FspFindFspHeader (PcdGet32 (PcdFspmBaseAddress));
  FspmUpdDataPtr = (FSPM_UPD_COMMON *)AllocateZeroPool ((UINTN)FspmHeaderPtr->CfgRegionSize);
  ASSERT (FspmUpdDataPtr != NULL);
  SourceData = (UINTN *)((UINTN)FspmHeaderPtr->ImageBase + (UINTN)FspmHeaderPtr->CfgRegionOffset);
  CopyMem (FspmUpdDataPtr, SourceData, (UINTN)FspmHeaderPtr->CfgRegionSize);

  DEBUG ((DEBUG_INFO, "UpdateFspmUpdData enter\n"));
  UpdateFspmUpdData ((VOID *)FspmUpdDataPtr);
  DEBUG ((DEBUG_INFO, "  NvsBufferPtr        - 0x%x\n", FspmUpdDataPtr->FspmArchUpd.NvsBufferPtr));
  DEBUG ((DEBUG_INFO, "  StackBase           - 0x%x\n", FspmUpdDataPtr->FspmArchUpd.StackBase));
  DEBUG ((DEBUG_INFO, "  StackSize           - 0x%x\n", FspmUpdDataPtr->FspmArchUpd.StackSize));
  DEBUG ((DEBUG_INFO, "  BootLoaderTolumSize - 0x%x\n", FspmUpdDataPtr->FspmArchUpd.BootLoaderTolumSize));
  DEBUG ((DEBUG_INFO, "  BootMode            - 0x%x\n", FspmUpdDataPtr->FspmArchUpd.BootMode));
  DEBUG ((DEBUG_INFO, "  HobListPtr          - 0x%x\n", &FspHobListPtr));

  TimeStampCounterStart = AsmReadTsc ();
  Status = CallFspMemoryInit (FspmUpdDataPtr, &FspHobListPtr);
  // Create hobs after memory initialization and not in temp RAM. Hence passing the recorded timestamp here
  PERF_START_EX(&gFspApiPerformanceGuid, "EventRec", NULL, TimeStampCounterStart, 0xD000);
  PERF_END_EX(&gFspApiPerformanceGuid, "EventRec", NULL, 0, 0xD07F);
  DEBUG ((DEBUG_INFO, "Total time spent executing FspMemoryInitApi: %d millisecond\n", DivU64x32 (GetTimeInNanoSecond (AsmReadTsc () - TimeStampCounterStart), 1000000)));
  if (EFI_ERROR(Status)) {
    DEBUG ((DEBUG_ERROR, "ERROR - Failed to execute FspMemoryInitApi(), Status = %r\n", Status));
  }
  DEBUG((DEBUG_INFO, "FspMemoryInit status: 0x%x\n", Status));
  ASSERT_EFI_ERROR (Status);


  Status = TestFspMemoryInitApiOutput (FspmUpdDataPtr, &FspHobListPtr);
  if (EFI_ERROR (Status)) {
    DEBUG ((DEBUG_ERROR, "ERROR - TestFspMemoryInitApiOutput () fail, Status = %r\n", Status));
  }

  DEBUG ((DEBUG_INFO, "  FspHobListPtr (returned) - 0x%x\n", FspHobListPtr));
  ASSERT (FspHobListPtr != NULL);

  PostFspmHobProcess (FspHobListPtr);

  //
  // FspHobList is not complete at this moment.
  // Save FspHobList pointer to hob, so that it can be got later
  //
  HobData = BuildGuidHob (
             &gFspHobGuid,
             sizeof (VOID *)
             );
  ASSERT (HobData != NULL);
  CopyMem (HobData, &FspHobListPtr, sizeof (FspHobListPtr));

  return Status;
}