EFI_STATUS GetTimerValue ( OUT UINT64 *TimerValue ) { *TimerValue = EfiReadTsc (); return EFI_SUCCESS; }
EFI_STATUS GetTimerValue ( OUT UINT64 *TimerValue ) /*++ Routine Description: Set TimerValue with current tick. Arguments: TimerValue - Timer value to be set Returns: EFI_SUCCESS - TimerValue is set. --*/ { *TimerValue = EfiReadTsc (); return EFI_SUCCESS; }
EFI_STATUS GetTimerValue ( OUT UINT64 *TimerValue ) /*++ Routine Description: Get timer value. Arguments: TimerValue - Pointer to the returned timer value Returns: EFI_SUCCESS - Successfully got timer value --*/ { *TimerValue = EfiReadTsc (); return EFI_SUCCESS; }
VOID WriteBootToOsPerformanceData ( VOID ) /*++ Routine Description: Allocates a block of memory and writes performance data of booting to OS into it. Arguments: None Returns: None --*/ { EFI_STATUS Status; EFI_CPU_ARCH_PROTOCOL *Cpu; EFI_PERFORMANCE_PROTOCOL *DrvPerf; UINT32 mAcpiLowMemoryLength; UINT32 LimitCount; EFI_PERF_HEADER mPerfHeader; EFI_PERF_DATA mPerfData; EFI_GAUGE_DATA *DumpData; EFI_HANDLE *Handles; UINTN NoHandles; UINT8 *Ptr; UINT8 *PdbFileName; UINT32 mIndex; UINT64 Ticker; UINT64 Freq; UINT32 Duration; UINT64 CurrentTicker; UINT64 TimerPeriod; // // Retrive time stamp count as early as possilbe // Ticker = EfiReadTsc (); // // Get performance architecture protocol // Status = gBS->LocateProtocol ( &gEfiPerformanceProtocolGuid, NULL, &DrvPerf ); if (EFI_ERROR (Status)) { return ; } // // Get CPU frequency // Status = gBS->LocateProtocol ( &gEfiCpuArchProtocolGuid, NULL, &Cpu ); if (EFI_ERROR (Status)) { return ; } // // Get Cpu Frequency // Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTicker, &TimerPeriod); if (EFI_ERROR (Status)) { return ; } // // Put Detailed performance data into memory // Handles = NULL; Status = gBS->LocateHandleBuffer ( AllHandles, NULL, NULL, &NoHandles, &Handles ); if (EFI_ERROR (Status)) { return ; } // // Allocate a block of memory that contain performance data to OS // if it is not allocated yet. // if (mAcpiLowMemoryBase == 0x0FFFFFFFF) { Status = gBS->AllocatePages ( AllocateMaxAddress, EfiReservedMemoryType, 4, &mAcpiLowMemoryBase ); if (EFI_ERROR (Status)) { gBS->FreePool (Handles); return ; } } mAcpiLowMemoryLength = EFI_PAGES_TO_SIZE(4); Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (EFI_PERF_HEADER)); LimitCount = (mAcpiLowMemoryLength - sizeof (EFI_PERF_HEADER)) / sizeof (EFI_PERF_DATA); // // Initialize performance data structure // EfiZeroMem (&mPerfHeader, sizeof (EFI_PERF_HEADER)); Freq = DivU64x32 (1000000000000, (UINTN) TimerPeriod, NULL); mPerfHeader.CpuFreq = Freq; // // Record BDS raw performance data // mPerfHeader.BDSRaw = Ticker; // // Get DXE drivers performance // for (mIndex = 0; mIndex < NoHandles; mIndex++) { Ticker = 0; PdbFileName = NULL; DumpData = DrvPerf->GetGauge ( DrvPerf, // Context NULL, // Handle NULL, // Token NULL, // Host NULL // PrecGauge ); while (DumpData) { if (DumpData->Handle == Handles[mIndex]) { PdbFileName = &(DumpData->PdbFileName[0]); if (DumpData->StartTick < DumpData->EndTick) { Ticker += (DumpData->EndTick - DumpData->StartTick); } } DumpData = DrvPerf->GetGauge ( DrvPerf, // Context NULL, // Handle NULL, // Token NULL, // Host DumpData // PrecGauge ); } Duration = (UINT32) DivU64x32 ( Ticker, (UINT32) Freq, NULL ); if (Duration > 0) { EfiZeroMem (&mPerfData, sizeof (EFI_PERF_DATA)); if (PdbFileName != NULL) { EfiAsciiStrCpy (mPerfData.Token, PdbFileName); } mPerfData.Duration = Duration; EfiCopyMem (Ptr, &mPerfData, sizeof (EFI_PERF_DATA)); Ptr += sizeof (EFI_PERF_DATA); mPerfHeader.Count++; if (mPerfHeader.Count == LimitCount) { goto Done; } } } gBS->FreePool (Handles); // // Get inserted performance data // DumpData = DrvPerf->GetGauge ( DrvPerf, // Context NULL, // Handle NULL, // Token NULL, // Host NULL // PrecGauge ); while (DumpData) { if ((DumpData->Handle) || (DumpData->StartTick > DumpData->EndTick)) { DumpData = DrvPerf->GetGauge ( DrvPerf, // Context NULL, // Handle NULL, // Token NULL, // Host DumpData // PrecGauge ); continue; } EfiZeroMem (&mPerfData, sizeof (EFI_PERF_DATA)); ConvertChar16ToChar8 ((UINT8 *) mPerfData.Token, DumpData->Token); mPerfData.Duration = (UINT32) DivU64x32 ( DumpData->EndTick - DumpData->StartTick, (UINT32) Freq, NULL ); EfiCopyMem (Ptr, &mPerfData, sizeof (EFI_PERF_DATA)); Ptr += sizeof (EFI_PERF_DATA); mPerfHeader.Count++; if (mPerfHeader.Count == LimitCount) { goto Done; } DumpData = DrvPerf->GetGauge ( DrvPerf, // Context NULL, // Handle NULL, // Token NULL, // Host DumpData // PrecGauge ); } Done: mPerfHeader.Signiture = 0x66726550; // // Put performance data to memory // EfiCopyMem ( (UINTN *) (UINTN) mAcpiLowMemoryBase, &mPerfHeader, sizeof (EFI_PERF_HEADER) ); gRT->SetVariable ( L"PerfDataMemAddr", &gEfiGenericVariableGuid, EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, sizeof (UINT32), (VOID *) &mAcpiLowMemoryBase ); return ; }
EFI_STATUS ExecElet ( IN OUT EFI_NETWORK_TEST_FILE *TestFile, IN CHAR16 *TestNodeName ) /*++ Routine Description: Execute an application. Arguments: TestFile - Pointer to the EFI_EFI_NETWORK_TEST_FILE structure. TestNodeName - Test node name string. Returns: EFI_SUCCESS - Operation succeeded. EFI_UNSUPPORTED - Unsupported test file. EFI_OUT_OF_RESOURCES - Memory allocation failed. Others - Some failure happened. --*/ { EFI_STATUS Status; UINTN ExitDataSize; CHAR16 *ExitData; EFI_HANDLE ImageHandle; EFI_DEVICE_PATH_PROTOCOL *FileNode; EFI_DEVICE_PATH_PROTOCOL *FilePath; EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; UINT64 StartTick; UINT64 StopTick; if ((TestFile->Type == EFI_NETWORK_TEST_FILE_APPLICATION) && (TestNodeName == NULL)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_TRACE, L"in ExecElet:begin exe (%s)", TestFile->FileName)); // // Add the file path to the device path // FileNode = FileDevicePath (NULL, TestFile->FileName); if (FileNode == NULL) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Create file device path - %r", EFI_OUT_OF_RESOURCES)); return EFI_OUT_OF_RESOURCES; } FilePath = AppendDevicePath (gEasFT->DevicePath, FileNode); if (FilePath == NULL) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Append file device path - %r", EFI_OUT_OF_RESOURCES)); BS->FreePool (FileNode); return EFI_OUT_OF_RESOURCES; } BS->FreePool (FileNode); // // Load the test file // Status = BS->LoadImage ( FALSE, gEasFT->ImageHandle, FilePath, NULL, 0, &ImageHandle ); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet:Load image - %r", Status)); BS->FreePool (FilePath); return Status; } BS->FreePool (FilePath); EFI_ENTS_STATUS ((L"in ExecElet: Finish Loading image file <%s>", TestFile->FileName)); // // Verify the image is an application or not // Status = BS->HandleProtocol ( ImageHandle, &gEfiLoadedImageProtocolGuid, (void **)&LoadedImage ); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"in ExecElet: HandleProtocol - %r", Status)); BS->UnloadImage(ImageHandle); return Status; } if (LoadedImage->ImageCodeType == EfiLoaderCode) { // // It is an application // #ifdef EFIARM StartTick = 0; #else StartTick = EfiReadTsc (); #endif Status = BS->StartImage ( ImageHandle, &ExitDataSize, &ExitData ); #ifdef EFIARM StopTick = 0; #else StopTick = EfiReadTsc (); #endif RecordExecTime (StartTick, StopTick); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in ExecElet: Start image - %r\n", Status)); } } else { EFI_ENTS_DEBUG ((EFI_ENTS_D_WARNING, L"Unsupported test file")); Status = EFI_UNSUPPORTED; } BS->UnloadImage(ImageHandle); return Status; } else if ((TestFile->Type == EFI_NETWORK_TEST_FILE_DRIVER) && (TestNodeName != NULL)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_TRACE, L"in ExecElet:begin exe (%s->%s)", TestFile->CmdName, TestNodeName)); Status = ExecDriver (TestFile, TestNodeName); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in ExecDriver: Status - %r\n", Status)); return Status; } } return EFI_SUCCESS; }
EFI_STATUS ExecDriver ( IN OUT EFI_NETWORK_TEST_FILE *TestFile, IN CHAR16 *TestNodeName ) /*++ Routine Description: Execute a driver. Arguments: TestFile - Pointer to the EFI_EFI_NETWORK_TEST_FILE structure. TestNodeName - Test node name string. Returns: EFI_SUCCESS - Operation succeeded. EFI_OUT_OF_RESOURCES - Memory allocation failed. Others - Some failure happened. --*/ { EFI_ENTS_PROTOCOL *EntsProtocol; ENTS_INTERFACE *EntsInterface; EFI_STATUS Status; EFI_STATUS TestStatus; RIVL_VARIABLE *DelayTimeVariable; UINT64 StartTick; UINT64 StopTick; // // Find the EntsProtocol instance by name // and install the client instance by index // Status = LocateEntsProtocol (TestFile->CmdName, &EntsProtocol); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in LocateEntsProtocol: Status - %r\n", Status)); return Status; } // // Find the EntsInterface by name // Status = LocateEntsInterface (EntsProtocol, TestNodeName, &EntsInterface); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in LocateEntsInterface: Status - %r\n", Status)); return Status; } // // Parse the argument list // Status = ParseArg (EntsInterface->ArgFieldList); if (EFI_ERROR (Status)) { EFI_ENTS_DEBUG ((EFI_ENTS_D_ERROR, L"Error in ParseArg: Status - %r\n", Status)); return Status; } // // Find variable (DelayTime) // DelayTimeVariable = SearchRivlVariable (DELAY_TIME_NAME); if (DelayTimeVariable != NULL) { BS->Stall (*(UINTN *) DelayTimeVariable->Address); } // // Call the entry point // #ifdef EFIARM StartTick = 0; #else StartTick = EfiReadTsc (); #endif TestStatus = EntsInterface->EntsInterfaceEntry (EntsProtocol->ClientInterface); #ifdef EFIARM StopTick = 0; #else StopTick = EfiReadTsc (); #endif RecordExecTime (StartTick, StopTick); if (EntsProtocol->RuntimeInfo != NULL) { (gEasFT->Cmd)->ComdRuntimeInfo = EntsStrDuplicate (EntsProtocol->RuntimeInfo); if ((gEasFT->Cmd)->ComdRuntimeInfo == NULL) { return EFI_OUT_OF_RESOURCES; } (gEasFT->Cmd)->ComdRuntimeInfoSize = (StrLen (EntsProtocol->RuntimeInfo) + 1) * 2; BS->FreePool (EntsProtocol->RuntimeInfo); EntsProtocol->RuntimeInfo = NULL; EntsProtocol->RuntimeInfoSize = 0; } return EFI_SUCCESS; }