/** 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; }
/** 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; }
/** 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; }
/** 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; }
/** 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; }