You've already forked slimbootloader
mirror of
https://github.com/Dasharo/slimbootloader.git
synced 2026-03-06 15:26:20 -08:00
FSP could produce a FSP boot performance HOB. So add the capability to print FSP performance data. Also add a PcdBootPerformanceMask to enable/disable boot performance data print. Signed-off-by: Guo Dong <guo.dong@intel.com>
399 lines
12 KiB
C
399 lines
12 KiB
C
/** @file
|
|
|
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
#include <PiPei.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BootloaderCommonLib.h>
|
|
#include <Library/LoaderPerformanceLib.h>
|
|
#include <Library/PrintLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Guid/LoaderFspInfoGuid.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include "ExtendedFirmwarePerformance.h"
|
|
|
|
/**
|
|
Convert GUID to String.
|
|
|
|
@param[in] Guid GUID to be converted
|
|
@param[out] Buffer Char buffer which will have GUID ascii string
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
GuidToStr (
|
|
IN EFI_GUID *Guid,
|
|
OUT CHAR8 *Buffer
|
|
)
|
|
{
|
|
AsciiSPrint (Buffer, 48, "%g", Guid);
|
|
}
|
|
|
|
/**
|
|
Provide default description string corresponding to Id.
|
|
|
|
@param[in] Id MeasurePoint Id
|
|
|
|
@retval Default description string
|
|
**/
|
|
CHAR8 *
|
|
EFIAPI
|
|
DefPerfIdToStr (
|
|
IN UINT32 Id
|
|
)
|
|
{
|
|
switch (Id) {
|
|
case 0x1000:
|
|
return "Reset vector";
|
|
case 0x1010:
|
|
return "Stage1A entry point";
|
|
case 0x1040:
|
|
return "Board PostTempRamInit hook";
|
|
case 0x1060:
|
|
return "Stage1A continuation";
|
|
case 0x1080:
|
|
return "Load Stage1B";
|
|
case 0x10A0:
|
|
return "Verify Stage1B";
|
|
case 0x10B0:
|
|
return "Decompress Stage1B";
|
|
case 0x2000:
|
|
return "Stage1B entry point";
|
|
case 0x2020:
|
|
return "Board PreMemoryInit hook";
|
|
case 0x2030:
|
|
return "FSP MemoryInit";
|
|
case 0x2040:
|
|
return "Board PostMemoryInit hook";
|
|
case 0x2050:
|
|
return "Board PreTempRamExit hook";
|
|
case 0x2060:
|
|
return "FSP TempRamExit";
|
|
case 0x2070:
|
|
return "Board PostTempRamExit hook";
|
|
case 0x2080:
|
|
return "Load Stage2";
|
|
case 0x2090:
|
|
return "Copy Stage2 to memory";
|
|
case 0x20A0:
|
|
return "Verify Stage2";
|
|
case 0x20B0:
|
|
return "Decompress Stage2";
|
|
case 0x20C0:
|
|
return "Extend Stage2 hash";
|
|
case 0x20D0:
|
|
return "Rebase Stage2";
|
|
case 0x3000:
|
|
return "Stage2 entry point";
|
|
case 0x3010:
|
|
return "Board PreSiliconInit hook";
|
|
case 0x3020:
|
|
return "Save NVS data";
|
|
case 0x3030:
|
|
return "FSP SiliconInit";
|
|
case 0x3040:
|
|
return "Board PostSiliconInit hook";
|
|
case 0x3050:
|
|
return "Display splash";
|
|
case 0x3060:
|
|
return "MP wake up";
|
|
case 0x3080:
|
|
return "MP init run";
|
|
case 0x3090:
|
|
return "Board PrePciEnumeration hook";
|
|
case 0x30A0:
|
|
return "PCI enumeration";
|
|
case 0x30B0:
|
|
return "Board PostPciEnumeration hook";
|
|
case 0x30C0:
|
|
return "FSP PostPciEnumeration notify";
|
|
case 0x30D0:
|
|
return "ACPI init";
|
|
case 0x30E0:
|
|
return "Board PrePayloadLoading hook";
|
|
case 0x3100:
|
|
return "Load payload";
|
|
case 0x3110:
|
|
return "Locate payload";
|
|
case 0x3120:
|
|
return "Copy payload to memory";
|
|
case 0x3130:
|
|
return "Verify payload";
|
|
case 0x3140:
|
|
return "Decompress payload";
|
|
case 0x3150:
|
|
return "Extend payload hash";
|
|
case 0x31A0:
|
|
return "Board PostPayloadLoading hook";
|
|
case 0x31B0:
|
|
return "Decode payload format";
|
|
case 0x31C0:
|
|
return "MP init done";
|
|
case 0x31D0:
|
|
return "FSP ReadyToBoot notify";
|
|
case 0x31E0:
|
|
return "FSP EndOfFirmware notify";
|
|
case 0x31F0:
|
|
return "End of stage2";
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Provide description string corresponding to FSP performance Id.
|
|
|
|
@param[in] Id MeasurePoint Id
|
|
|
|
@retval Default description string
|
|
**/
|
|
CHAR8 *
|
|
FspPerfIdToStr (
|
|
IN UINT32 Id
|
|
)
|
|
{
|
|
|
|
switch (Id) {
|
|
case 0xF000:
|
|
return "TempRamInit entry";
|
|
case 0xF07F:
|
|
return "TempRamInit exit";
|
|
case 0xD000:
|
|
return "MemoryInit entry";
|
|
case 0xD07F:
|
|
return "MemoryInit exit";
|
|
case 0xB000:
|
|
return "TempRamExit entry";
|
|
case 0xB07F:
|
|
return "TempRamExit exit";
|
|
case 0x9000:
|
|
return "SiliconInit entry";
|
|
case 0x907F:
|
|
return "SiliconInit exit";
|
|
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
Provide description string corresponding to Id.
|
|
|
|
If there is a description in default description table corresponding to Id,
|
|
default description will be printed
|
|
If there is no description in default description table,
|
|
look for description in overrided description table once if it is provided
|
|
Otherwise,
|
|
just print empty string
|
|
|
|
@param[in] Id MeasurePoint Id
|
|
@param[in] PerfIdToStrTbl A pointer to description table
|
|
|
|
@retval Description string
|
|
**/
|
|
CHAR8 *
|
|
EFIAPI
|
|
PerfIdToStr (
|
|
IN UINT32 Id,
|
|
IN PERF_ID_TO_STR PerfIdToStrTbl
|
|
)
|
|
{
|
|
CHAR8 *Desc;
|
|
|
|
Desc = DefPerfIdToStr (Id);
|
|
if ((Desc == NULL) && (PerfIdToStrTbl != NULL)) {
|
|
Desc = PerfIdToStrTbl (Id);
|
|
}
|
|
|
|
if (Desc == NULL) {
|
|
Desc = " ";
|
|
}
|
|
|
|
return Desc;
|
|
}
|
|
|
|
|
|
/**
|
|
Get Measurement form Fpdt records.
|
|
|
|
@param[in] RecordHeader Pointer to the FPDT record.
|
|
@param[out] Measurement Pointer to the measurement which need to be filled.
|
|
|
|
**/
|
|
VOID
|
|
GetMeasurementInfo (
|
|
IN EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader,
|
|
OUT MEASUREMENT_RECORD *Measurement
|
|
)
|
|
{
|
|
switch (RecordHeader->Type) {
|
|
case FPDT_GUID_EVENT_TYPE:
|
|
CopyMem (&(Measurement->ModuleGuid), &(((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Guid), sizeof (EFI_GUID));
|
|
Measurement->Identifier = ((UINT32)((FPDT_GUID_EVENT_RECORD *)RecordHeader)->ProgressID);
|
|
Measurement->StartTimeStamp = ((FPDT_GUID_EVENT_RECORD *)RecordHeader)->Timestamp;
|
|
Measurement->Token = "PEIM";
|
|
break;
|
|
|
|
case FPDT_DYNAMIC_STRING_EVENT_TYPE:
|
|
CopyMem (&(Measurement->ModuleGuid), &(((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Guid), sizeof (EFI_GUID));
|
|
Measurement->Identifier = ((UINT32)((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);
|
|
Measurement->StartTimeStamp = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
|
|
Measurement->Token = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;
|
|
Measurement->Module = ((FPDT_DYNAMIC_STRING_EVENT_RECORD *)RecordHeader)->String;
|
|
|
|
break;
|
|
|
|
case FPDT_GUID_QWORD_EVENT_TYPE:
|
|
CopyMem (&(Measurement->ModuleGuid), &(((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Guid), sizeof (EFI_GUID));
|
|
Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->ProgressID);
|
|
Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_EVENT_RECORD *)RecordHeader)->Timestamp;
|
|
Measurement->Token = "LoadImage";
|
|
break;
|
|
|
|
case FPDT_GUID_QWORD_STRING_EVENT_TYPE:
|
|
CopyMem (&(Measurement->ModuleGuid), &(((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->Guid), sizeof (EFI_GUID));
|
|
Measurement->Identifier = ((UINT32)((FPDT_GUID_QWORD_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);
|
|
Measurement->StartTimeStamp = ((FPDT_GUID_QWORD_STRING_EVENT_RECORD*)RecordHeader)->Timestamp;
|
|
Measurement->Token = "DB_start";
|
|
break;
|
|
|
|
case FPDT_DUAL_GUID_STRING_EVENT_TYPE:
|
|
CopyMem (&(Measurement->ModuleGuid), &(((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Guid1), sizeof (EFI_GUID));
|
|
Measurement->Identifier = ((UINT32)((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->ProgressID);
|
|
Measurement->StartTimeStamp = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->Timestamp;
|
|
Measurement->Token = ((FPDT_DUAL_GUID_STRING_EVENT_RECORD *)RecordHeader)->String;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (FspPerfIdToStr (Measurement->Identifier) != NULL) {
|
|
Measurement->Token = FspPerfIdToStr (Measurement->Identifier);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
Print FSP Measure Point information.
|
|
|
|
**/
|
|
VOID
|
|
PrintFspPerfData (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 *FspFirmwarePerformance;
|
|
EFI_HOB_GUID_TYPE *GuidHob;
|
|
FPDT_PEI_EXT_PERF_HEADER *FspPerformanceLogHeader;
|
|
MEASUREMENT_RECORD Rec;
|
|
EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *RecordHeader;
|
|
UINT8 *StartRecordEvent;
|
|
UINT32 DataSize;
|
|
UINT32 Time;
|
|
LOADER_FSP_INFO *FspInfo;
|
|
|
|
// Get FSP Info HOB
|
|
FspInfo = GetFirstGuidHob (&gLoaderFspInfoGuid);
|
|
if (FspInfo == NULL) {
|
|
return;
|
|
}
|
|
FspInfo = GET_GUID_HOB_DATA (FspInfo);
|
|
|
|
FspFirmwarePerformance = NULL;
|
|
GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, FspInfo->FspHobList);
|
|
while (GuidHob != NULL) {
|
|
FspFirmwarePerformance = (UINT8*)GET_GUID_HOB_DATA (GuidHob);
|
|
FspPerformanceLogHeader = (FPDT_PEI_EXT_PERF_HEADER *)FspFirmwarePerformance;
|
|
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, " FspPerfHob: HobIsFull - 0x%x\n", FspPerformanceLogHeader->HobIsFull));
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, " FspPerfHob: SizeOfAllEntries - 0x%x\n", FspPerformanceLogHeader->SizeOfAllEntries));
|
|
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, " Dump performance data for FSP HOB:\n"));
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, " Id | Time (ms) | Token | Module \n"));
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, "------+------------+--------------------------|--------------------------\n"));
|
|
|
|
DataSize = 0;
|
|
RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(FspFirmwarePerformance + sizeof (FPDT_PEI_EXT_PERF_HEADER));
|
|
StartRecordEvent = (UINT8 *)RecordHeader;
|
|
while (DataSize < FspPerformanceLogHeader->SizeOfAllEntries) {
|
|
RecordHeader = (EFI_ACPI_5_0_FPDT_PERFORMANCE_RECORD_HEADER *)(StartRecordEvent + DataSize);
|
|
GetMeasurementInfo (RecordHeader, &Rec);
|
|
Time = (UINT32)DivU64x32 (Rec.StartTimeStamp, 1000000);
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, " %4X | %7d ms | %-25a| %g\n", Rec.Identifier, Time, Rec.Token, Rec.ModuleGuid));
|
|
DataSize += RecordHeader->Length;
|
|
}
|
|
|
|
//
|
|
// Previous HOB is used, then find next one.
|
|
//
|
|
GuidHob = GetNextGuidHob (&gEdkiiFpdtExtendedFirmwarePerformanceGuid, GET_NEXT_HOB (GuidHob));
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, "------+------------+--------------------------|--------------------------\n"));
|
|
}
|
|
|
|
|
|
/**
|
|
Print Bootloader Measure Point information.
|
|
|
|
@param[in] PerfData A pointer indicating BL_PERF_DATA instance to print performance data
|
|
@param[in] PerfIdToStrTbl A pointer to description table corresponding to Id
|
|
|
|
**/
|
|
VOID
|
|
PrintBootloaderPerfData (
|
|
IN BL_PERF_DATA *PerfData,
|
|
IN PERF_ID_TO_STR PerfIdToStrTbl
|
|
)
|
|
{
|
|
UINT32 Idx;
|
|
UINT32 Time;
|
|
UINT32 PrevTime;
|
|
UINT16 Id;
|
|
UINT64 Tsc;
|
|
const CHAR8 *Desc;
|
|
|
|
PrevTime = 0;
|
|
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, " Id | Time (ms) | Delta (ms) | Description \n"));
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, "------+------------+------------+----------------------------------\n"));
|
|
for (Idx = 0; Idx < PerfData->PerfIndex; Idx++) {
|
|
Tsc = PerfData->TimeStamp[Idx];
|
|
Id = ((UINT16 *)&Tsc)[3];
|
|
((UINT16 *)&Tsc)[3] = 0;
|
|
Time = (UINT32)DivU64x32 (Tsc, PerfData->FreqKhz);
|
|
Desc = PerfIdToStr (Id, PerfIdToStrTbl);
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, " %4X | %7d ms | %7d ms | %a\n", Id, Time, Time - PrevTime, Desc));
|
|
PrevTime = Time;
|
|
}
|
|
DEBUG ((DEBUG_INFO | DEBUG_EVENT, "------+------------+------------+----------------------------------\n"));
|
|
}
|
|
|
|
/**
|
|
Print Bootloader Measure Point information.
|
|
|
|
@param[in] PerfData A pointer indicating BL_PERF_DATA instance to print performance data
|
|
@param[in] PerfIdToStrTbl A pointer to description table corresponding to Id
|
|
|
|
**/
|
|
VOID
|
|
EFIAPI
|
|
PrintMeasurePoint (
|
|
IN BL_PERF_DATA *PerfData,
|
|
IN PERF_ID_TO_STR PerfIdToStrTbl
|
|
)
|
|
{
|
|
// Print bootloader performance
|
|
if ((PcdGet32 (PcdBootPerformanceMask) & BIT0) != 0) {
|
|
PrintBootloaderPerfData (PerfData, PerfIdToStrTbl);
|
|
}
|
|
|
|
// Print FSP boot performance
|
|
if ((PcdGet32 (PcdBootPerformanceMask) & BIT1) != 0) {
|
|
PrintFspPerfData ();
|
|
}
|
|
}
|