CloverBootloader/Library/OcDebugLogLib/OcAppleLog.c

315 lines
6.0 KiB
C

/** @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 <Uefi.h>
#include <IndustryStandard/ApplePerfData.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/OcDebugLogLib.h>
#include <Library/OcMiscLib.h>
#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;
}
}