/** Dumps all the PEI performance log to DXE performance gauge array. This internal function dumps all the PEI performance log to the DXE performance gauge array. It retrieves the optional GUID HOB for PEI performance and then saves the performance data to DXE performance data structures. **/ VOID InternalGetPeiPerformance ( VOID ) { EFI_HOB_GUID_TYPE *GuidHob; PEI_PERFORMANCE_LOG_HEADER *LogHob; PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray; UINT32 *LogIdArray; GAUGE_DATA_ENTRY_EX *GaugeEntryExArray; UINT32 Index; UINT32 NumberOfEntries; NumberOfEntries = 0; GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1); // // Dump PEI Log Entries to DXE Guage Data structure. // GuidHob = GetFirstGuidHob (&gPerformanceProtocolGuid); if (GuidHob != NULL) { LogHob = GET_GUID_HOB_DATA (GuidHob); LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (LogHob + 1); NumberOfEntries = LogHob->NumberOfEntries; for (Index = 0; Index < NumberOfEntries; Index++) { GaugeEntryExArray[Index].Handle = LogEntryArray[Index].Handle; AsciiStrnCpy (GaugeEntryExArray[Index].Token, LogEntryArray[Index].Token, DXE_PERFORMANCE_STRING_LENGTH); AsciiStrnCpy (GaugeEntryExArray[Index].Module, LogEntryArray[Index].Module, DXE_PERFORMANCE_STRING_LENGTH); GaugeEntryExArray[Index].StartTimeStamp = LogEntryArray[Index].StartTimeStamp; GaugeEntryExArray[Index].EndTimeStamp = LogEntryArray[Index].EndTimeStamp; GaugeEntryExArray[Index].Identifier = 0; } GuidHob = GetFirstGuidHob (&gPerformanceExProtocolGuid); if (GuidHob != NULL) { LogIdArray = GET_GUID_HOB_DATA (GuidHob); for (Index = 0; Index < NumberOfEntries; Index++) { GaugeEntryExArray[Index].Identifier = LogIdArray[Index]; } } } mGaugeData->NumberOfEntries = NumberOfEntries; }
/** This is a callback function when packets are received or transmitted in Mtftp driver. A callback function that is provided by the caller to intercept the EFI_MTFTP6_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). @param[in] This Pointer to EFI_MTFTP4_PROTOCOL. @param[in] Token Pointer to EFI_MTFTP4_TOKEN. @param[in] PacketLen Length of EFI_MTFTP4_PACKET. @param[in] Packet Pointer to EFI_MTFTP4_PACKET to be checked. @retval EFI_SUCCESS The current operation succeeeded. @retval EFI_ABORTED Abort the current transfer process. **/ EFI_STATUS EFIAPI PxeBcMtftp4CheckPacket ( IN EFI_MTFTP4_PROTOCOL *This, IN EFI_MTFTP4_TOKEN *Token, IN UINT16 PacketLen, IN EFI_MTFTP4_PACKET *Packet ) { PXEBC_PRIVATE_DATA *Private; EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; EFI_STATUS Status; Private = (PXEBC_PRIVATE_DATA *) Token->Context; Callback = Private->PxeBcCallback; Status = EFI_SUCCESS; if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) { // // Store the tftp error message into mode data and set the received flag. // Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpy ( Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH ); } if (Callback != NULL) { // // Callback to user if has when received any tftp packet. // Status = Callback->Callback ( Callback, Private->Function, TRUE, PacketLen, (EFI_PXE_BASE_CODE_PACKET *) Packet ); if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { // // User wants to abort current process if not EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. // Status = EFI_ABORTED; } else { // // User wants to continue current process if EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. // Status = EFI_SUCCESS; } } return Status; }
/** Creates a record for the beginning of a performance measurement. Creates a record that contains the Handle, Token, Module and Identifier. If TimeStamp is not zero, then TimeStamp is added to the record as the start time. If TimeStamp is zero, then this function reads the current time stamp and adds that time stamp value to the record as the start time. @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 TimeStamp 64-bit time stamp. @param Identifier 32-bit identifier. If the value is 0, the created record is same as the one created by StartPerformanceMeasurement. @retval RETURN_SUCCESS The start of the measurement was recorded. @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. **/ RETURN_STATUS EFIAPI StartPerformanceMeasurementEx ( IN CONST VOID *Handle, OPTIONAL IN CONST CHAR8 *Token, OPTIONAL IN CONST CHAR8 *Module, OPTIONAL IN UINT64 TimeStamp, IN UINT32 Identifier ) { PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog; UINT32 *PeiPerformanceIdArray; PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray; UINT32 Index; InternalGetPerformanceHobLog (&PeiPerformanceLog, &PeiPerformanceIdArray); if (PeiPerformanceLog->NumberOfEntries >= PcdGet8 (PcdMaxPeiPerformanceLogEntries)) { return RETURN_OUT_OF_RESOURCES; } Index = PeiPerformanceLog->NumberOfEntries++; LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1); LogEntryArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle; if (Token != NULL) { AsciiStrnCpy (LogEntryArray[Index].Token, Token, PEI_PERFORMANCE_STRING_LENGTH); } if (Module != NULL) { AsciiStrnCpy (LogEntryArray[Index].Module, Module, PEI_PERFORMANCE_STRING_LENGTH); } LogEntryArray[Index].EndTimeStamp = 0; PeiPerformanceIdArray[Index] = Identifier; if (TimeStamp == 0) { TimeStamp = GetPerformanceCounter (); } LogEntryArray[Index].StartTimeStamp = TimeStamp; return RETURN_SUCCESS; }
/** This is a callback function when packets received/transmitted in Mtftp driver. A callback function that is provided by the caller to intercept the EFI_MTFTP4_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). @param This Pointer to Mtftp protocol instance @param Token Pointer to Mtftp token @param PacketLen Length of Mtftp packet @param Packet Pointer to Mtftp packet @retval EFI_SUCCESS Operation sucess @retval EFI_ABORTED Abort transfer process **/ EFI_STATUS EFIAPI PxeBcCheckPacket ( IN EFI_MTFTP4_PROTOCOL *This, IN EFI_MTFTP4_TOKEN *Token, IN UINT16 PacketLen, IN EFI_MTFTP4_PACKET *Packet ) { PXEBC_PRIVATE_DATA *Private; EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; EFI_STATUS Status; Private = (PXEBC_PRIVATE_DATA *) Token->Context; Callback = Private->PxeBcCallback; Status = EFI_SUCCESS; if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) { Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpy (Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, 127); } if (Callback != NULL) { Status = Callback->Callback ( Callback, Private->Function, TRUE, PacketLen, (EFI_PXE_BASE_CODE_PACKET *) Packet ); if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { Status = EFI_ABORTED; } else { Status = EFI_SUCCESS; } } return Status; }
/** 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 ; }
/** Adds a record at the end of the performance measurement log that records the start time of a performance measurement. Adds a record to the end of the performance measurement log that contains the Handle, Token, Module and Identifier. The end time of the new record must be set to zero. If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record. If TimeStamp is zero, the start time in the record is filled in with the value read from the current time stamp. @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 TimeStamp 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 The data was read correctly from the device. @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement. **/ EFI_STATUS EFIAPI StartGaugeEx ( IN CONST VOID *Handle, OPTIONAL IN CONST CHAR8 *Token, OPTIONAL IN CONST CHAR8 *Module, OPTIONAL IN UINT64 TimeStamp, IN UINT32 Identifier ) { GAUGE_DATA_ENTRY_EX *GaugeEntryExArray; UINTN GaugeDataSize; GAUGE_DATA_HEADER *NewGaugeData; UINTN OldGaugeDataSize; GAUGE_DATA_HEADER *OldGaugeData; UINT32 Index; Index = mGaugeData->NumberOfEntries; if (Index >= mMaxGaugeRecords) { // // Try to enlarge the scale of gauge array. // OldGaugeData = mGaugeData; OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords; GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY_EX) * mMaxGaugeRecords * 2; NewGaugeData = AllocateZeroPool (GaugeDataSize); if (NewGaugeData == NULL) { return EFI_OUT_OF_RESOURCES; } mGaugeData = NewGaugeData; mMaxGaugeRecords *= 2; // // Initialize new data array and migrate old data one. // mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize); FreePool (OldGaugeData); } GaugeEntryExArray = (GAUGE_DATA_ENTRY_EX *) (mGaugeData + 1); GaugeEntryExArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle; if (Token != NULL) { AsciiStrnCpy (GaugeEntryExArray[Index].Token, Token, DXE_PERFORMANCE_STRING_LENGTH); } if (Module != NULL) { AsciiStrnCpy (GaugeEntryExArray[Index].Module, Module, DXE_PERFORMANCE_STRING_LENGTH); } GaugeEntryExArray[Index].EndTimeStamp = 0; GaugeEntryExArray[Index].Identifier = Identifier; if (TimeStamp == 0) { TimeStamp = GetPerformanceCounter (); } GaugeEntryExArray[Index].StartTimeStamp = TimeStamp; mGaugeData->NumberOfEntries++; return EFI_SUCCESS; }
EFI_STATUS BootMenuUpdateBootOption ( IN LIST_ENTRY *BootOptionsList ) { EFI_STATUS Status; BDS_LOAD_OPTION_ENTRY *BootOptionEntry; BDS_LOAD_OPTION *BootOption; BDS_LOAD_OPTION_SUPPORT* DeviceSupport; ARM_BDS_LOADER_ARGUMENTS* BootArguments; CHAR16 BootDescription[BOOT_DEVICE_DESCRIPTION_MAX]; CHAR8 CmdLine[BOOT_DEVICE_OPTION_MAX]; CHAR16 UnicodeCmdLine[BOOT_DEVICE_OPTION_MAX]; EFI_DEVICE_PATH *DevicePath; EFI_DEVICE_PATH *TempInitrdPath; ARM_BDS_LOADER_TYPE BootType; ARM_BDS_LOADER_OPTIONAL_DATA* LoaderOptionalData; ARM_BDS_LINUX_ARGUMENTS* LinuxArguments; EFI_DEVICE_PATH *InitrdPathNodes; EFI_DEVICE_PATH *InitrdPath; UINTN InitrdSize; UINTN CmdLineSize; BOOLEAN InitrdSupport; UINT8* OptionalData; UINTN OptionalDataSize; BOOLEAN IsPrintable; BOOLEAN IsUnicode; DisplayBootOptions (BootOptionsList); Status = SelectBootOption (BootOptionsList, UPDATE_BOOT_ENTRY, &BootOptionEntry); if (EFI_ERROR (Status)) { return Status; } BootOption = BootOptionEntry->BdsLoadOption; // Get the device support for this Boot Option Status = BootDeviceGetDeviceSupport (BootOption->FilePathList, &DeviceSupport); if (EFI_ERROR(Status)) { Print(L"Not possible to retrieve the supported device for the update\n"); return EFI_UNSUPPORTED; } Status = DeviceSupport->UpdateDevicePathNode (BootOption->FilePathList, L"EFI Application or the kernel", &DevicePath); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (DeviceSupport->RequestBootType) { Status = BootDeviceGetType (DevicePath, &BootType, &BootOption->Attributes); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } } LoaderOptionalData = BootOption->OptionalData; if (LoaderOptionalData != NULL) { BootType = (ARM_BDS_LOADER_TYPE)ReadUnaligned32 ((UINT32 *)(&LoaderOptionalData->Header.LoaderType)); } else { BootType = BDS_LOADER_EFI_APPLICATION; } if ((BootType == BDS_LOADER_KERNEL_LINUX_ATAG) || (BootType == BDS_LOADER_KERNEL_LINUX_FDT)) { LinuxArguments = &LoaderOptionalData->Arguments.LinuxArguments; CmdLineSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->CmdLineSize); InitrdSize = ReadUnaligned16 ((CONST UINT16*)&LinuxArguments->InitrdSize); if (InitrdSize > 0) { Print(L"Keep the initrd: "); } else { Print(L"Add an initrd: "); } Status = GetHIInputBoolean (&InitrdSupport); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto EXIT; } if (InitrdSupport) { if (InitrdSize > 0) { // Case we update the initrd device path Status = DeviceSupport->UpdateDevicePathNode ((EFI_DEVICE_PATH*)((UINTN)(LinuxArguments + 1) + CmdLineSize), L"initrd", &InitrdPath); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) {// EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; } InitrdSize = GetDevicePathSize (InitrdPath); } else { // Case we create the initrd device path Status = DeviceSupport->CreateDevicePathNode (L"initrd", &InitrdPathNodes); if (EFI_ERROR(Status) && Status != EFI_NOT_FOUND) { // EFI_NOT_FOUND is returned on empty input string, but we can boot without an initrd Status = EFI_ABORTED; goto EXIT; } if (InitrdPathNodes != NULL) { // Duplicate Linux kernel Device Path TempInitrdPath = DuplicateDevicePath (BootOption->FilePathList); // Replace Linux kernel Node by EndNode SetDevicePathEndNode (GetLastDevicePathNode (TempInitrdPath)); // Append the Device Path to the selected device path InitrdPath = AppendDevicePath (TempInitrdPath, (CONST EFI_DEVICE_PATH_PROTOCOL *)InitrdPathNodes); FreePool (TempInitrdPath); // Free the InitrdPathNodes created by Support->CreateDevicePathNode() FreePool (InitrdPathNodes); if (InitrdPath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto EXIT; } InitrdSize = GetDevicePathSize (InitrdPath); } else { InitrdPath = NULL; } } } else { InitrdSize = 0; } Print(L"Arguments to pass to the binary: "); if (CmdLineSize > 0) { AsciiStrnCpy (CmdLine, (CONST CHAR8*)(LinuxArguments + 1), sizeof (CmdLine)); CmdLine[sizeof (CmdLine) - 1] = '\0'; } else { CmdLine[0] = '\0'; } Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } CmdLineSize = AsciiStrSize (CmdLine); OptionalDataSize = sizeof(ARM_BDS_LOADER_ARGUMENTS) + CmdLineSize + InitrdSize; BootArguments = (ARM_BDS_LOADER_ARGUMENTS*)AllocatePool (OptionalDataSize); BootArguments->LinuxArguments.CmdLineSize = CmdLineSize; BootArguments->LinuxArguments.InitrdSize = InitrdSize; CopyMem (&BootArguments->LinuxArguments + 1, CmdLine, CmdLineSize); CopyMem ((VOID*)((UINTN)(&BootArguments->LinuxArguments + 1) + CmdLineSize), InitrdPath, InitrdSize); OptionalData = (UINT8*)BootArguments; } else { Print (L"Arguments to pass to the EFI Application: "); if (BootOption->OptionalDataSize > 0) { IsPrintable = IsPrintableString (BootOption->OptionalData, &IsUnicode); if (IsPrintable) { // // The size in bytes of the string, final zero included, should // be equal to or at least lower than "BootOption->OptionalDataSize" // and the "IsPrintableString()" has already tested that the length // in number of characters is smaller than BOOT_DEVICE_OPTION_MAX, // final '\0' included. We can thus copy the string for editing // using "CopyMem()". Furthermore, note that in the case of an Unicode // string "StrnCpy()" and "StrCpy()" can not be used to copy the // string because the data pointed to by "BootOption->OptionalData" // is not necessarily 2-byte aligned. // if (IsUnicode) { CopyMem ( UnicodeCmdLine, BootOption->OptionalData, MIN (sizeof (UnicodeCmdLine), BootOption->OptionalDataSize) ); } else { CopyMem ( CmdLine, BootOption->OptionalData, MIN (sizeof (CmdLine), BootOption->OptionalDataSize) ); } } } else { UnicodeCmdLine[0] = L'\0'; IsPrintable = TRUE; IsUnicode = TRUE; } // We do not request arguments for OptionalData that cannot be printed if (IsPrintable) { if (IsUnicode) { Status = EditHIInputStr (UnicodeCmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } OptionalData = (UINT8*)UnicodeCmdLine; OptionalDataSize = StrSize (UnicodeCmdLine); } else { Status = EditHIInputAscii (CmdLine, BOOT_DEVICE_OPTION_MAX); if (EFI_ERROR (Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } OptionalData = (UINT8*)CmdLine; OptionalDataSize = AsciiStrSize (CmdLine); } } else { // We keep the former OptionalData OptionalData = BootOption->OptionalData; OptionalDataSize = BootOption->OptionalDataSize; } } Print(L"Description for this new Entry: "); StrnCpy (BootDescription, BootOption->Description, BOOT_DEVICE_DESCRIPTION_MAX); Status = EditHIInputStr (BootDescription, BOOT_DEVICE_DESCRIPTION_MAX); if (EFI_ERROR(Status)) { Status = EFI_ABORTED; goto FREE_DEVICE_PATH; } // Update the entry Status = BootOptionUpdate (BootOption, BootOption->Attributes, BootDescription, DevicePath, BootType, OptionalData, OptionalDataSize); FREE_DEVICE_PATH: FreePool (DevicePath); EXIT: if (Status == EFI_ABORTED) { Print(L"\n"); } return Status; }
/** This function is to get size of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully obtained the size of file. @retval EFI_NOT_FOUND Parse the tftp options failed. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Did not obtain the size of the file. **/ EFI_STATUS PxeBcMtftp4GetFileSize ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN OUT UINT64 *BufferSize ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_OPTION ReqOpt[2]; EFI_MTFTP4_PACKET *Packet; EFI_MTFTP4_OPTION *Option; UINT32 PktLen; UINT8 OptBuf[128]; UINT32 OptCnt; EFI_STATUS Status; *BufferSize = 0; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; Packet = NULL; Option = NULL; PktLen = 0; OptCnt = 1; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } // // Build the required options for get info. // ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; PxeBcUintnToAscDec (0, OptBuf); ReqOpt[0].ValueStr = OptBuf; if (BlockSize != NULL) { ReqOpt[1].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[1].ValueStr = (UINT8 *) (ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1); PxeBcUintnToAscDec (*BlockSize, ReqOpt[1].ValueStr); OptCnt++; } Status = Mtftp4->GetInfo ( Mtftp4, FALSE, Filename, NULL, (UINT8) OptCnt, ReqOpt, &PktLen, &Packet ); if (EFI_ERROR (Status)) { if (Status == EFI_TFTP_ERROR) { // // Store the tftp error message into mode data and set the received flag. // Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpy ( Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH ); } goto ON_ERROR; } // // Parse the options in the reply packet. // OptCnt = 0; Status = Mtftp4->ParseOptions ( Mtftp4, PktLen, Packet, (UINT32 *) &OptCnt, &Option ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Parse out the value of "tsize" option. // Status = EFI_NOT_FOUND; while (OptCnt != 0) { if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr)); Status = EFI_SUCCESS; } OptCnt--; } FreePool (Option); ON_ERROR: if (Packet != NULL) { FreePool (Packet); } Mtftp4->Configure (Mtftp4, NULL); return Status; }
/** This function is to get size of a file by Tftp. @param Private Pointer to PxeBc private data @param Config Pointer to Mtftp configuration data @param Filename Pointer to file name @param BlockSize Pointer to block size @param BufferSize Pointer to buffer size @retval EFI_SUCCESS Get the size of file success @retval EFI_NOT_FOUND Parse the tftp ptions failed. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Other Has not get the size of the file. **/ EFI_STATUS PxeBcTftpGetFileSize ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN OUT UINT64 *BufferSize ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_OPTION ReqOpt[2]; EFI_MTFTP4_PACKET *Packet; EFI_MTFTP4_OPTION *Option; UINT32 PktLen; UINT8 OptBuf[128]; UINT32 OptCnt; EFI_STATUS Status; *BufferSize = 0; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; Packet = NULL; Option = NULL; PktLen = 0; OptCnt = 1; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; UtoA10 (0, (CHAR8 *) OptBuf); ReqOpt[0].ValueStr = OptBuf; if (BlockSize != NULL) { ReqOpt[1].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[1].ValueStr = ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1; UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[1].ValueStr); OptCnt++; } Status = Mtftp4->GetInfo ( Mtftp4, FALSE, Filename, NULL, (UINT8) OptCnt, ReqOpt, &PktLen, &Packet ); if (EFI_ERROR (Status)) { if (Status == EFI_TFTP_ERROR) { Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpy ( Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, 127 ); } goto ON_ERROR; } OptCnt = 0; Status = Mtftp4->ParseOptions ( Mtftp4, PktLen, Packet, (UINT32 *) &OptCnt, &Option ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = EFI_NOT_FOUND; while (OptCnt != 0) { if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { *BufferSize = AtoU64 (Option[OptCnt - 1].ValueStr); Status = EFI_SUCCESS; } OptCnt--; } FreePool (Option); ON_ERROR: if (Packet != NULL) { FreePool (Packet); } Mtftp4->Configure (Mtftp4, NULL); return Status; }
/** 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; }