/** @file Copyright (C) 2020, vit9696. All rights reserved. All rights reserved. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ #include #include #include #include #include #include #include #include #include #include "OcLogInternal.h" STATIC BOOLEAN mAppleDebugLogEnable; STATIC CHAR8 mCurrentBuffer[1024]; STATIC APPLE_PERF_DATA * mApplePerfBuffer; STATIC UINTN mApplePerfBufferSize; STATIC UINT32 mApplePerfDumped; STATIC EFI_STATUS EFIAPI AppleDebugLogPrintToOcLog ( IN OC_LOG_PROTOCOL *OcLog, IN CONST CHAR8 *Format, ... ) { EFI_STATUS Status; VA_LIST Marker; VA_START (Marker, Format); Status = OcLog->AddEntry ( OcLog, DEBUG_INFO, Format, Marker ); VA_END (Marker); return Status; } STATIC EFI_STATUS EFIAPI AppleDebugLogPrint ( IN CONST CHAR8 *Message ) { OC_LOG_PROTOCOL *OcLog; EFI_STATUS Status; UINTN Length; CHAR8 *NewLinePos; APPLE_PERF_ENTRY *Entry; UINT32 Index; if (!mAppleDebugLogEnable) { return FALSE; } OcLog = InternalGetOcLog (); if (OcLog == NULL) { return EFI_NOT_FOUND; } // // Flush perf data. // if (mApplePerfBuffer != NULL && mApplePerfBuffer->Signature == APPLE_PERF_DATA_SIGNATURE && mApplePerfBuffer->NumberOfEntries > mApplePerfDumped) { Entry = APPLE_PERF_FIRST_ENTRY (mApplePerfBuffer); for (Index = 0; Index < mApplePerfBuffer->NumberOfEntries; ++Index) { if (Index == mApplePerfDumped) { AppleDebugLogPrintToOcLog ( OcLog, "EBPF: [%u ms] %a\n", (UINT32) Entry->TimestampMs, Entry->EntryData ); ++mApplePerfDumped; } Entry = APPLE_PERF_NEXT_ENTRY (Entry); } } // // Concatenate with the previous message. // Status = AsciiStrCatS ( mCurrentBuffer, sizeof (mCurrentBuffer) - 1, Message ); if (EFI_ERROR (Status)) { Length = AsciiStrLen (mCurrentBuffer); if (Length > 0) { // // Flush the previous message. // if (mCurrentBuffer[Length - 1] != '\n') { // // Ensure it is terminated with a newline. // mCurrentBuffer[Length] = '\n'; mCurrentBuffer[Length+1] = '\0'; } AppleDebugLogPrintToOcLog ( OcLog, "AAPL: %a", Message ); mCurrentBuffer[0] = '\0'; // // Append the new message again. // Status = AsciiStrCpyS ( mCurrentBuffer, sizeof (mCurrentBuffer) - 1, Message ); } // // New message does not fit, send it directly. // if (EFI_ERROR (Status)) { return AppleDebugLogPrintToOcLog ( OcLog, "AAPL: %a", Message ); } } // // New message is in the buffer, send it line-by-line. // while (TRUE) { NewLinePos = AsciiStrStr (mCurrentBuffer, "\n"); if (NewLinePos == NULL) { break; } AppleDebugLogPrintToOcLog ( OcLog, "AAPL: %.*a", (UINTN) (NewLinePos - mCurrentBuffer + 1), mCurrentBuffer ); Length = AsciiStrLen (NewLinePos + 1); if (Length > 0) { CopyMem (mCurrentBuffer, NewLinePos + 1, Length + 1); } else { mCurrentBuffer[0] = '\0'; } } return EFI_SUCCESS; } STATIC EFI_STATUS EFIAPI AppleDebugLogExtractBuffer ( IN OUT UINT32 *Position, IN OUT UINTN *BufferSize, OUT CHAR8 *Buffer OPTIONAL, OUT UINT32 *LostCharacters OPTIONAL ) { // // Do nothing for now. // return EFI_END_OF_FILE; } STATIC EFI_STATUS EFIAPI AppleDebugLogWriteFiles ( VOID ) { // // Do nothing for now. // return EFI_SUCCESS; } STATIC VOID EFIAPI AppleDebugLogSetupFiles ( VOID ) { // // Do nothing for now. // } STATIC APPLE_DEBUG_LOG_PROTOCOL mAppleDebugLogProtocol = { .Revision = APPLE_DEBUG_LOG_PROTOCOL_REVISION, .Print = AppleDebugLogPrint, .ExtractBuffer = AppleDebugLogExtractBuffer, .WriteFiles = AppleDebugLogWriteFiles, .SetupFiles = AppleDebugLogSetupFiles }; APPLE_DEBUG_LOG_PROTOCOL * OcAppleDebugLogInstallProtocol ( IN BOOLEAN Reinstall ) { EFI_STATUS Status; APPLE_DEBUG_LOG_PROTOCOL *Protocol; EFI_HANDLE Handle; if (Reinstall) { Status = OcUninstallAllProtocolInstances (&gAppleDebugLogProtocolGuid); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "OCL: Uninstall failed: %r\n", Status)); return NULL; } } else { Status = gBS->LocateProtocol ( &gAppleDebugLogProtocolGuid, NULL, (VOID *) &Protocol ); if (!EFI_ERROR (Status)) { return Protocol; } } Handle = NULL; Status = gBS->InstallMultipleProtocolInterfaces ( &Handle, &gAppleDebugLogProtocolGuid, (VOID **) &mAppleDebugLogProtocol, NULL ); if (EFI_ERROR (Status)) { return NULL; } return &mAppleDebugLogProtocol; } VOID OcAppleDebugLogConfigure ( IN BOOLEAN Enable ) { mAppleDebugLogEnable = Enable; } VOID OcAppleDebugLogPerfAllocated ( IN OUT VOID *PerfBuffer, IN UINTN PerfBufferSize ) { DEBUG ((DEBUG_INFO, "OCL: EFI Boot performance buffer %p (%u)\n", PerfBuffer, (UINT32) PerfBufferSize)); if (mAppleDebugLogEnable) { ZeroMem (PerfBuffer, PerfBufferSize); mApplePerfBuffer = PerfBuffer; mApplePerfBufferSize = PerfBufferSize; mApplePerfDumped = 0; } }