21#include <Library/BaseLib.h>
22#include <Library/DebugLib.h>
23#include <Library/BaseMemoryLib.h>
24#include <Library/MemoryAllocationLib.h>
25#include <Library/PcdLib.h>
26#include <Library/PrintLib.h>
34#include <Library/SerialPortLib.h>
35#include <Library/UefiLib.h>
36#include <Library/UefiBootServicesTableLib.h>
37#include <Library/UefiRuntimeServicesTableLib.h>
49 UINT64 dTStartSec = 0;
53 UINT64 CurrentTsc = 0;
90 "%02d:%03d %02d:%03d ",
103 IN CONST CHAR16 *LogPrefixPath
111 if (LogPrefixPath == NULL) {
115 Status =
gRT->GetTime (&Date, NULL);
116 if (EFI_ERROR (Status)) {
117 ZeroMem (&Date,
sizeof (Date));
120 Size = StrSize (LogPrefixPath) +
L_STR_SIZE (L
"-0000-00-00-000000.txt");
122 LogPath = AllocatePool (
Size);
123 if (LogPath == NULL) {
130 L
"%s-%04u-%02u-%02u-%02u%02u%02u.txt",
146 IN CONST CHAR8 *FormattedString,
153 ASSERT (FormattedString != NULL);
158 Char = FormattedString[
Pos];
164 return EFI_NOT_FOUND;
175 return EFI_NOT_FOUND;
185 return EFI_NOT_FOUND;
191 if (!(
IsAsciiNumber (Char) || ((Char >=
'A') && (Char <=
'Z')))) {
192 return EFI_NOT_FOUND;
206 IN CONST CHAR8 *FormattedString,
208 IN BOOLEAN BlacklistFiltering
216 ASSERT (FormattedString != NULL);
221 if (FlexFilters == NULL) {
226 if (EFI_ERROR (Status)) {
227 AsciiStrCpyS (Prefix,
ARRAY_SIZE (Prefix),
"?");
230 for (Index = 0; Index < FlexFilters->Count; ++Index) {
234 if (AsciiStrCmp (Prefix, *Value) == 0) {
238 return BlacklistFiltering;
245 return !BlacklistFiltering;
255 IN BOOLEAN BlacklistFiltering,
256 IN CONST CHAR8 *FormatString,
273 sizeof (Private->LineBuffer),
281 if ( ((ErrorLevel & (DEBUG_WARN | DEBUG_ERROR)) == 0)
282 &&
IsPrefixFiltered (Private->LineBuffer, Private->FlexFilters, Private->BlacklistFiltering))
291 Status = EFI_SUCCESS;
293 if (*Private->LineBuffer !=
'\0') {
299 if (((OcLog->Options &
OC_LOG_CONSOLE) != 0) && ((OcLog->DisplayLevel & ErrorLevel) != 0)) {
301 Private->UnicodeLineBuffer,
302 sizeof (Private->UnicodeLineBuffer),
306 gST->ConOut->OutputString (
gST->ConOut, Private->UnicodeLineBuffer);
308 if (OcLog->DisplayDelay > 0) {
309 gBS->Stall (OcLog->DisplayDelay);
313 TimingLength = (UINT32)AsciiStrLen (Private->TimingTxt);
314 LineLength = (UINT32)AsciiStrLen (Private->LineBuffer);
323 SerialPortWrite ((UINT8 *)Private->TimingTxt, TimingLength);
324 SerialPortWrite ((UINT8 *)Private->LineBuffer, LineLength);
331 if (Private->DataHub == NULL) {
332 gBS->LocateProtocol (
335 (VOID **)&Private->DataHub
339 if (Private->DataHub != NULL) {
341 DataSize = TimingLength + LineLength + 1;
342 TotalSize = KeySize + DataSize +
sizeof (*Entry);
344 Entry = AllocatePool (TotalSize);
347 ZeroMem (Entry,
sizeof (*Entry));
352 (CHAR16 *)&Entry->
Data[0],
356 Private->LogCounter++
371 Private->DataHub->LogData (
388 Status = AsciiStrCatS (Private->AsciiBuffer, Private->AsciiBufferSize, Private->TimingTxt);
389 if (!EFI_ERROR (Status)) {
390 Private->AsciiBufferWrittenOffset += AsciiStrLen (Private->TimingTxt);
391 Status = AsciiStrCatS (Private->AsciiBuffer, Private->AsciiBufferSize, Private->LineBuffer);
392 if (!EFI_ERROR (Status)) {
393 Private->AsciiBufferWrittenOffset += AsciiStrLen (Private->LineBuffer);
400 if (((OcLog->Options &
OC_LOG_FILE) != 0) && (OcLog->FileSystem != NULL)) {
405 if (EfiGetCurrentTpl () <= TPL_CALLBACK) {
406 if (OcLog->UnsafeLogFile != NULL) {
411 ASSERT (Private->AsciiBufferWrittenOffset >= Private->AsciiBufferFlushedOffset);
412 WriteSize = Private->AsciiBufferWrittenOffset - Private->AsciiBufferFlushedOffset;
413 WrittenSize = WriteSize;
414 OcLog->UnsafeLogFile->Write (OcLog->UnsafeLogFile, &WrittenSize, &Private->AsciiBuffer[Private->AsciiBufferFlushedOffset]);
415 OcLog->UnsafeLogFile->Flush (OcLog->UnsafeLogFile);
416 Private->AsciiBufferFlushedOffset += WrittenSize;
417 if (WriteSize != WrittenSize) {
420 "OCL: Log write truncated %u to %u\n",
433 Private->AsciiBuffer,
434 (UINT32)Private->AsciiBufferSize
448 if (Private->NvramBufferSize - AsciiStrSize (Private->NvramBuffer) >= AsciiStrLen (Private->LineBuffer)) {
449 Status = AsciiStrCatS (Private->NvramBuffer, Private->NvramBufferSize, Private->LineBuffer);
451 Status = EFI_BUFFER_TOO_SMALL;
454 if (!EFI_ERROR (Status)) {
455 Attributes = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS;
457 Attributes |= EFI_VARIABLE_NON_VOLATILE;
464 Status =
gRT->SetVariable (
468 AsciiStrLen (Private->NvramBuffer),
472 if (EFI_ERROR (Status)) {
478 gST->ConOut->OutputString (
gST->ConOut, L
"NVRAM is full, cannot log!\r\n");
483 gST->ConOut->OutputString (
gST->ConOut, L
"NVRAM log size exceeded, cannot log!\r\n");
498 IN CONST CHAR8 *FormatString,
506 ASSERT (FormatString != NULL);
519 if ( ((ErrorLevel & OcLog->HaltLevel) != 0)
520 && (AsciiStrnCmp (FormatString,
"\nASSERT_RETURN_ERROR",
L_STR_LEN (
"\nASSERT_RETURN_ERROR")) != 0)
521 && (AsciiStrnCmp (FormatString,
"\nASSERT_EFI_ERROR",
L_STR_LEN (
"\nASSERT_EFI_ERROR")) != 0))
523 gST->ConOut->OutputString (
gST->ConOut, L
"Halting on critical error\r\n");
535 OUT CHAR8 **OcLogBuffer
542 Status = EFI_INVALID_PARAMETER;
544 if (OcLogBuffer != NULL) {
548 Status = EFI_SUCCESS;
558 IN UINT32 NonVolatile OPTIONAL,
559 IN EFI_DEVICE_PATH_PROTOCOL *
FilePath OPTIONAL
562 return EFI_NOT_FOUND;
583 if (mInternalOcLog == NULL) {
584 Status =
gBS->LocateProtocol (
587 (VOID **)&mInternalOcLog
590 if (EFI_ERROR (Status) || (mInternalOcLog->Revision !=
OC_LOG_REVISION)) {
591 mInternalOcLog = NULL;
595 return mInternalOcLog;
601 IN CONST CHAR8 *LogModules,
602 IN UINT32 DisplayDelay,
603 IN UINTN DisplayLevel,
605 IN CONST CHAR16 *LogPrefixPath OPTIONAL,
606 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *LogFileSystem OPTIONAL
614 EFI_FILE_PROTOCOL *LogRoot;
616 EFI_FILE_PROTOCOL *UnsafeLogFile;
618 ASSERT (LogModules != NULL);
623 UnsafeLogFile = NULL;
625 if (LogPath != NULL) {
626 if (LogFileSystem != NULL) {
627 Status = LogFileSystem->OpenVolume (LogFileSystem, &LogRoot);
628 if (EFI_ERROR (Status)) {
631 LogRoot->Close (LogRoot);
636 if (LogRoot == NULL) {
638 if (EFI_ERROR (Status)) {
639 DEBUG ((DEBUG_ERROR,
"OCL: There is no place to write log file to - %r\n", Status));
649 EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
652 if (EFI_ERROR (Status)) {
653 DEBUG ((DEBUG_ERROR,
"OCL: Failure opening log file - %r\n", Status));
654 UnsafeLogFile = NULL;
655 LogRoot->Close (LogRoot);
660 if (LogRoot == NULL) {
668 UnsafeLogFile = NULL;
702 Status = EFI_SUCCESS;
704 Private = AllocateZeroPool (
sizeof (*Private));
705 Status = EFI_OUT_OF_RESOURCES;
707 if (Private != NULL) {
729 if ((*LogModules !=
'*') && (*LogModules !=
'\0')) {
733 if (*LogModules ==
'+') {
735 }
else if (*LogModules ==
'-') {
744 Status =
gBS->InstallProtocolInterface (
747 EFI_NATIVE_INTERFACE,
751 if (!EFI_ERROR (Status)) {
752 OcLog = &Private->
OcLog;
759 if (LogRoot != NULL) {
760 if (!EFI_ERROR (Status)) {
773 if (UnsafeLogFile != NULL) {
774 UnsafeLogFile->Close (UnsafeLogFile);
777 LogRoot->Close (LogRoot);
EFI_GUID gApplePlatformProducerNameGuid
#define ARRAY_SIZE(Array)
EFI_GUID gEfiMiscSubClassGuid
#define EFI_DATA_RECORD_CLASS_DATA
EFI_GUID gEfiDataHubProtocolGuid
DMG_FILEPATH_DEVICE_PATH FilePath
DMG_SIZE_DEVICE_PATH Size
UINT64 OcGetTSCFrequency(VOID)
#define OC_LOG_BUFFER_SIZE
BOOLEAN OcIsWritableFileSystem(IN EFI_FILE_PROTOCOL *Fs)
EFI_STATUS OcSetFileData(IN EFI_FILE_PROTOCOL *WritableFs OPTIONAL, IN CONST CHAR16 *FileName, IN CONST VOID *Buffer, IN UINT32 Size)
EFI_STATUS OcSafeFileOpen(IN CONST EFI_FILE_PROTOCOL *Directory, OUT EFI_FILE_PROTOCOL **NewHandle, IN CONST CHAR16 *FileName, IN CONST UINT64 OpenMode, IN CONST UINT64 Attributes)
EFI_STATUS OcFindWritableFileSystem(IN OUT EFI_FILE_PROTOCOL **WritableFs)
VOID * OcFlexArrayItemAt(IN CONST OC_FLEX_ARRAY *FlexArray, IN CONST UINTN Index)
OC_FLEX_ARRAY * OcStringSplit(IN CONST VOID *String, IN CONST CHAR16 Delim, IN CONST OC_STRING_FORMAT StringFormat)
STATIC CHAR16 * GetLogPath(IN CONST CHAR16 *LogPrefixPath)
OC_LOG_PROTOCOL * InternalGetOcLog(VOID)
EFI_STATUS EFIAPI OcLogResetTimers(IN OC_LOG_PROTOCOL *This)
STATIC BOOLEAN IsPrefixFiltered(IN CONST CHAR8 *FormattedString, IN CONST OC_FLEX_ARRAY *FlexFilters OPTIONAL, IN BOOLEAN BlacklistFiltering)
EFI_STATUS EFIAPI OcLogAddEntry(IN OC_LOG_PROTOCOL *OcLog, IN UINTN ErrorLevel, IN CONST CHAR8 *FormatString, IN VA_LIST Marker)
STATIC EFI_STATUS InternalLogAddEntry(IN OC_LOG_PRIVATE_DATA *Private, IN OC_LOG_PROTOCOL *OcLog, IN UINTN ErrorLevel, IN CONST OC_FLEX_ARRAY *FlexFilters OPTIONAL, IN BOOLEAN BlacklistFiltering, IN CONST CHAR8 *FormatString, IN VA_LIST Marker)
EFI_STATUS EFIAPI OcLogSaveLog(IN OC_LOG_PROTOCOL *This, IN UINT32 NonVolatile OPTIONAL, IN EFI_DEVICE_PATH_PROTOCOL *FilePath OPTIONAL)
STATIC CHAR8 * GetTiming(IN OC_LOG_PROTOCOL *This)
STATIC EFI_STATUS GetLogPrefix(IN CONST CHAR8 *FormattedString, OUT CHAR8 *Prefix)
EFI_STATUS OcConfigureLogProtocol(IN OC_LOG_OPTIONS Options, IN CONST CHAR8 *LogModules, IN UINT32 DisplayDelay, IN UINTN DisplayLevel, IN UINTN HaltLevel, IN CONST CHAR16 *LogPrefixPath OPTIONAL, IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *LogFileSystem OPTIONAL)
EFI_STATUS EFIAPI OcLogGetLog(IN OC_LOG_PROTOCOL *This, OUT CHAR8 **OcLogBuffer)
EFI_GUID gOcLogProtocolGuid
A global variable storing the GUID of the OC_LOG_PROTOCOL.
#define OC_LOG_NONVOLATILE
#define OC_LOG_PREFIX_CHAR_MAX
#define OC_LOG_TIMING_BUFFER_SIZE
#define OC_LOG_NVRAM_BUFFER_SIZE
#define OC_LOG_PRIVATE_DATA_FROM_OC_LOG_THIS(a)
#define OC_LOG_PRIVATE_DATA_SIGNATURE
#define SECONDS_TO_MICROSECONDS(x)
BOOLEAN IsAsciiNumber(IN CHAR8 Char)
#define L_STR_LEN(String)
#define L_STR_SIZE(String)
APPLE_EVENT_HANDLE Handle
#define OC_LOG_VARIABLE_NAME
EFI_GUID gOcVendorVariableGuid
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_RUNTIME_SERVICES * gRT
UINT64 EFIAPI MultU64x32(IN UINT64 Multiplicand, IN UINT32 Multiplier)
UINT64 EFIAPI DivU64x64Remainder(IN UINT64 Dividend, IN UINT64 Divisor, OUT UINT64 *Remainder OPTIONAL)
UINT64 EFIAPI AsmReadTsc(VOID)
BOOLEAN BlacklistFiltering
CHAR8 TimingTxt[OC_LOG_TIMING_BUFFER_SIZE]
CHAR8 AsciiBuffer[OC_LOG_BUFFER_SIZE]
OC_FLEX_ARRAY * FlexFilters
OC_LOG_ADD_ENTRY AddEntry
A pointer to the AddEntry function.
UINTN DisplayLevel
The error level visible onscreen.
EFI_FILE_PROTOCOL * UnsafeLogFile
Log file, owned. Unsafe logging only.
UINT32 Revision
The revision of the installed protocol.
CHAR16 * FilePath
Log file path.
OC_LOG_RESET_TIMERS ResetTimers
A pointer to the ResetTimers function.
OC_LOG_SAVE_LOG SaveLog
A pointer to the SaveLog function.
OC_LOG_GET_LOG GetLog
A pointer to the GetLog function.
UINTN HaltLevel
The error level causing CPU dead loop.
UINT32 DisplayDelay
The delay after visible onscreen message in microseconds.
EFI_FILE_PROTOCOL * FileSystem
Log file system root, not owned.
OC_LOG_OPTIONS Options
The current options of the installed protocol.