From 20e7a77431f19c30cb1b730982b65cefa8afc2a9 Mon Sep 17 00:00:00 2001 From: xli24 Date: Mon, 27 Apr 2009 06:35:40 +0000 Subject: Update directory/file names for status code runtime dxe driver. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@8180 6f19259b-4bc3-4df7-8a09-765794883524 --- .../RuntimeDxe/DataHubStatusCodeWorker.c | 379 +++++++++++++++++++++ .../RuntimeDxe/RtMemoryStatusCodeWorker.c | 105 ++++++ .../StatusCode/RuntimeDxe/SerialStatusCodeWorker.c | 194 +++++++++++ .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c | 325 ++++++++++++++++++ .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h | 241 +++++++++++++ .../StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf | 93 +++++ 6 files changed, 1337 insertions(+) create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf (limited to 'IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe') diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c new file mode 100644 index 0000000000..743f6185a2 --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/DataHubStatusCodeWorker.c @@ -0,0 +1,379 @@ +/** @file + Data Hub status code worker. + + Copyright (c) 2006 - 2009, Intel Corporation + 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 "StatusCodeRuntimeDxe.h" + +// +// Initialize FIFO to cache records. +// +LIST_ENTRY mRecordsFifo = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo); +LIST_ENTRY mRecordsBuffer = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer); +UINT32 mLogDataHubStatus = 0; +EFI_EVENT mLogDataHubEvent; +// +// Cache data hub protocol. +// +EFI_DATA_HUB_PROTOCOL *mDataHubProtocol; + + +/** + Retrieve one record of from free record buffer. This record is removed from + free record buffer. + + This function retrieves one record from free record buffer. + If the pool has been exhausted, then new memory would be allocated for it. + + @return Pointer to the free record. + NULL means failure to allocate new memeory for free record buffer. + +**/ +DATA_HUB_STATUS_CODE_DATA_RECORD * +AcquireRecordBuffer ( + VOID + ) +{ + DATAHUB_STATUSCODE_RECORD *Record; + EFI_TPL CurrentTpl; + LIST_ENTRY *Node; + UINT32 Index; + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + if (!IsListEmpty (&mRecordsBuffer)) { + // + // Strip one entry from free record buffer. + // + Node = GetFirstNode (&mRecordsBuffer); + RemoveEntryList (Node); + + Record = BASE_CR (Node, DATAHUB_STATUSCODE_RECORD, Node); + } else { + if (CurrentTpl > TPL_NOTIFY) { + // + // Memory management should work at <=TPL_NOTIFY + // + gBS->RestoreTPL (CurrentTpl); + return NULL; + } + + // + // If free record buffer is exhausted, then allocate 16 new records for it. + // + gBS->RestoreTPL (CurrentTpl); + Record = (DATAHUB_STATUSCODE_RECORD *) AllocateZeroPool (sizeof (DATAHUB_STATUSCODE_RECORD) * 16); + if (Record == NULL) { + return NULL; + } + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + // + // Here we only insert 15 new records to the free record buffer, for the first record + // will be returned immediately. + // + for (Index = 1; Index < 16; Index++) { + InsertTailList (&mRecordsBuffer, &Record[Index].Node); + } + } + + Record->Signature = DATAHUB_STATUS_CODE_SIGNATURE; + InsertTailList (&mRecordsFifo, &Record->Node); + + gBS->RestoreTPL (CurrentTpl); + + return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data); +} + + +/** + Retrieve one record from Records FIFO. The record would be removed from FIFO. + + @return Point to record, which is ready to be logged. + NULL means the FIFO of record is empty. + +**/ +DATA_HUB_STATUS_CODE_DATA_RECORD * +RetrieveRecord ( + VOID + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData; + DATAHUB_STATUSCODE_RECORD *Record; + LIST_ENTRY *Node; + EFI_TPL CurrentTpl; + + RecordData = NULL; + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + if (!IsListEmpty (&mRecordsFifo)) { + Node = GetFirstNode (&mRecordsFifo); + Record = CR (Node, DATAHUB_STATUSCODE_RECORD, Node, DATAHUB_STATUS_CODE_SIGNATURE); + ASSERT (Record != NULL); + + RemoveEntryList (&Record->Node); + RecordData = (DATA_HUB_STATUS_CODE_DATA_RECORD *) Record->Data; + } + + gBS->RestoreTPL (CurrentTpl); + + return RecordData; +} + +/** + Release given record and return it to free record buffer. + + @param RecordData Pointer to the record to release. + +**/ +VOID +ReleaseRecord ( + DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData + ) +{ + DATAHUB_STATUSCODE_RECORD *Record; + EFI_TPL CurrentTpl; + + Record = CR (RecordData, DATAHUB_STATUSCODE_RECORD, Data[0], DATAHUB_STATUS_CODE_SIGNATURE); + ASSERT (Record != NULL); + + CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL); + + InsertTailList (&mRecordsBuffer, &Record->Node); + Record->Signature = 0; + + gBS->RestoreTPL (CurrentTpl); +} + +/** + Report status code into DataHub. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR Function is reentered. + @retval EFI_DEVICE_ERROR Function is called at runtime. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. + +**/ +EFI_STATUS +DataHubStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *Record; + UINT32 ErrorLevel; + VA_LIST Marker; + CHAR8 *Format; + UINTN CharCount; + + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 0) == 1) { + return EFI_DEVICE_ERROR; + } + + // + // See whether in runtime phase or not. + // + if (EfiAtRuntime ()) { + return EFI_DEVICE_ERROR; + } + + Record = AcquireRecordBuffer (); + if (Record == NULL) { + // + // There are no empty record buffer in private buffers + // + return EFI_OUT_OF_RESOURCES; + } + + // + // Construct Data Hub Extended Data + // + Record->CodeType = CodeType; + Record->Value = Value; + Record->Instance = Instance; + + if (CallerId != NULL) { + CopyMem (&Record->CallerId, CallerId, sizeof (EFI_GUID)); + } + + if (Data != NULL) { + if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + CharCount = UnicodeVSPrintAsciiFormat ( + (CHAR16 *) (Record + 1), + EFI_STATUS_CODE_DATA_MAX_SIZE, + Format, + Marker + ); + // + // Change record data type to DebugType. + // + CopyGuid (&Record->Data.Type, &gEfiStatusCodeDataTypeDebugGuid); + Record->Data.HeaderSize = Data->HeaderSize; + Record->Data.Size = (UINT16) ((CharCount + 1) * sizeof (CHAR16)); + } else { + // + // Copy status code data header + // + CopyMem (&Record->Data, Data, sizeof (EFI_STATUS_CODE_DATA)); + + if (Data->Size > EFI_STATUS_CODE_DATA_MAX_SIZE) { + Record->Data.Size = EFI_STATUS_CODE_DATA_MAX_SIZE; + } + CopyMem ((VOID *) (Record + 1), Data + 1, Record->Data.Size); + } + } + + gBS->SignalEvent (mLogDataHubEvent); + + return EFI_SUCCESS; +} + + +/** + The Event handler which will be notified to log data in Data Hub. + + @param Event Instance of the EFI_EVENT to signal whenever data is + available to be logged in the system. + @param Context Context of the event. + +**/ +VOID +EFIAPI +LogDataHubEventCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *Record; + UINT32 Size; + UINT64 DataRecordClass; + + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mLogDataHubStatus, 0, 1) == 1) { + return; + } + + // + // Log DataRecord in Data Hub. + // Journal records fifo to find all record entry. + // + while (TRUE) { + // + // Retrieve record from record FIFO until no more record can be retrieved. + // + Record = RetrieveRecord (); + if (Record == NULL) { + break; + } + // + // Add in the size of the header we added. + // + Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + (UINT32) Record->Data.Size; + + if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR; + } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG; + } else { + // + // Should never get here. + // + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } + + // + // Log DataRecord in Data Hub + // + mDataHubProtocol->LogData ( + mDataHubProtocol, + &gEfiDataHubStatusCodeRecordGuid, + &gEfiStatusCodeRuntimeProtocolGuid, + DataRecordClass, + Record, + Size + ); + + ReleaseRecord (Record); + } + + // + // Restore the nest status of report + // + InterlockedCompareExchange32 (&mLogDataHubStatus, 1, 0); +} + + +/** + Locate Data Hub Protocol and create event for logging data + as initialization for data hub status code worker. + + @retval EFI_SUCCESS Initialization is successful. + +**/ +EFI_STATUS +DataHubStatusCodeInitializeWorker ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + (VOID **) &mDataHubProtocol + ); + ASSERT_EFI_ERROR (Status); + + // + // Create a Notify Event to log data in Data Hub + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, + LogDataHubEventCallBack, + NULL, + &mLogDataHubEvent + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c new file mode 100644 index 0000000000..e67c31d3e3 --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/RtMemoryStatusCodeWorker.c @@ -0,0 +1,105 @@ +/** @file + Runtime memory status code worker. + + Copyright (c) 2006 - 2009, Intel Corporation + 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 "StatusCodeRuntimeDxe.h" + +RUNTIME_MEMORY_STATUSCODE_HEADER *mRtMemoryStatusCodeTable; + +/** + Initialize runtime memory status code table as initialization for runtime memory status code worker + + @retval EFI_SUCCESS Runtime memory status code table successfully initialized. + +**/ +EFI_STATUS +RtMemoryStatusCodeInitializeWorker ( + VOID + ) +{ + // + // Allocate runtime memory status code pool. + // + mRtMemoryStatusCodeTable = AllocateRuntimePool ( + sizeof (RUNTIME_MEMORY_STATUSCODE_HEADER) + + PcdGet16 (PcdStatusCodeRuntimeMemorySize) * + 1024 + ); + ASSERT (mRtMemoryStatusCodeTable != NULL); + + mRtMemoryStatusCodeTable->RecordIndex = 0; + mRtMemoryStatusCodeTable->NumberOfRecords = 0; + mRtMemoryStatusCodeTable->MaxRecordsNumber = + (PcdGet16 (PcdStatusCodeRuntimeMemorySize) * 1024) / sizeof (MEMORY_STATUSCODE_RECORD); + + return EFI_SUCCESS; +} + + +/** + Report status code into runtime memory. If the runtime pool is full, roll back to the + first record and overwrite it. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + + @retval EFI_SUCCESS Status code successfully recorded in runtime memory status code table. + +**/ +EFI_STATUS +RtMemoryStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance + ) +{ + MEMORY_STATUSCODE_RECORD *Record; + + // + // Locate current record buffer. + // + Record = (MEMORY_STATUSCODE_RECORD *) (mRtMemoryStatusCodeTable + 1); + Record = &Record[mRtMemoryStatusCodeTable->RecordIndex++]; + + // + // Save status code. + // + Record->CodeType = CodeType; + Record->Value = Value; + Record->Instance = Instance; + + // + // If record index equals to max record number, then wrap around record index to zero. + // + // The reader of status code should compare the number of records with max records number, + // If it is equal to or larger than the max number, then the wrap-around had happened, + // so the first record is pointed by record index. + // If it is less then max number, index of the first record is zero. + // + mRtMemoryStatusCodeTable->NumberOfRecords++; + if (mRtMemoryStatusCodeTable->RecordIndex == mRtMemoryStatusCodeTable->MaxRecordsNumber) { + // + // Wrap around record index. + // + mRtMemoryStatusCodeTable->RecordIndex = 0; + } + + return EFI_SUCCESS; +} + + + diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c new file mode 100644 index 0000000000..710a808ada --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/SerialStatusCodeWorker.c @@ -0,0 +1,194 @@ +/** @file + Serial I/O status code reporting worker. + + Copyright (c) 2006 - 2009, Intel Corporation + 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 "StatusCodeRuntimeDxe.h" + +EFI_SERIAL_IO_PROTOCOL *mSerialIoProtocol; + +/** + Locates Serial I/O Protocol as initialization for serial status code worker. + + @retval EFI_SUCCESS Serial I/O Protocol is successfully located. + +**/ +EFI_STATUS +EfiSerialStatusCodeInitializeWorker ( + VOID + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiSerialIoProtocolGuid, + NULL, + (VOID **) &mSerialIoProtocol + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + +/** + Convert status code value and extended data to readable ASCII string, send string to serial I/O device. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS Status code reported to serial I/O successfully. + @retval EFI_DEVICE_ERROR EFI serial device cannot work after ExitBootService() is called. + @retval EFI_DEVICE_ERROR EFI serial device cannot work with TPL higher than TPL_CALLBACK. + +**/ +EFI_STATUS +SerialStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + CHAR8 *Filename; + CHAR8 *Description; + CHAR8 *Format; + CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + UINT32 ErrorLevel; + UINT32 LineNumber; + UINTN CharCount; + VA_LIST Marker; + + if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) { + if (EfiAtRuntime ()) { + return EFI_DEVICE_ERROR; + } + if (EfiGetCurrentTpl () > TPL_CALLBACK ) { + return EFI_DEVICE_ERROR; + } + } + + Buffer[0] = '\0'; + + if (Data != NULL && + ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) { + // + // Print ASSERT() information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "\n\rDXE_ASSERT!: %a (%d): %a\n\r", + Filename, + LineNumber, + Description + ); + } else if (Data != NULL && + ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + // + // Print DEBUG() information into output buffer. + // + CharCount = AsciiVSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + Format, + Marker + ); + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + // + // Print ERROR information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "ERROR: C%x:V%x I%x", + CodeType, + Value, + Instance + ); + + if (CallerId != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + " %g", + CallerId + ); + } + + if (Data != NULL) { + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + " %x", + Data + ); + } + + CharCount += AsciiSPrint ( + &Buffer[CharCount - 1], + (EFI_STATUS_CODE_DATA_MAX_SIZE - (sizeof (Buffer[0]) * CharCount)), + "\n\r" + ); + } else if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + // + // Print PROGRESS information into output buffer. + // + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "PROGRESS CODE: V%x I%x\n\r", + Value, + Instance + ); + } else { + // + // Code type is not defined. + // + CharCount = AsciiSPrint ( + Buffer, + EFI_STATUS_CODE_DATA_MAX_SIZE, + "Undefined: C%x:V%x I%x\n\r", + CodeType, + Value, + Instance + ); + } + + + if (FeaturePcdGet (PcdStatusCodeUseHardSerial)) { + // + // Call SerialPort Lib function to do print. + // + SerialPortWrite ((UINT8 *) Buffer, CharCount); + } + if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) { + mSerialIoProtocol->Write ( + mSerialIoProtocol, + &CharCount, + Buffer + ); + } + + return EFI_SUCCESS; +} + diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c new file mode 100644 index 0000000000..12651153f5 --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.c @@ -0,0 +1,325 @@ +/** @file + Status code driver for IA32/X64/EBC architecture. + + Copyright (c) 2006 - 2009, Intel Corporation + 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 "StatusCodeRuntimeDxe.h" + +EFI_EVENT mVirtualAddressChangeEvent = NULL; +EFI_HANDLE mHandle = NULL; + +// +// Declaration of status code protocol. +// +EFI_STATUS_CODE_PROTOCOL mEfiStatusCodeProtocol = { + ReportDispatcher +}; + +// +// Report operation nest status. +// If it is set, then the report operation has nested. +// +UINT32 mStatusCodeNestStatus = 0; + +/** + Entry point of DXE Status Code Driver. + + This function is the entry point of this DXE Status Code Driver. + It installs Status Code Runtime Protocol, and registers event for EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + +**/ +EFI_STATUS +EFIAPI +StatusCodeRuntimeDxeEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + // + // Dispatch initialization request to supported devices + // + InitializationDispatcherWorker (); + + // + // Install Status Code Runtime Protocol implementation as defined in PI Specification. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mHandle, + &gEfiStatusCodeRuntimeProtocolGuid, + &mEfiStatusCodeProtocol, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + VirtualAddressChangeCallBack, + NULL, + &gEfiEventVirtualAddressChangeGuid, + &mVirtualAddressChangeEvent + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + Report status code to all supported device. + + This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). + It calls into the workers which dispatches the platform specific listeners. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. + +**/ +EFI_STATUS +EFIAPI +ReportDispatcher ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + // + // Use atom operation to avoid the reentant of report. + // If current status is not zero, then the function is reentrancy. + // + if (InterlockedCompareExchange32 (&mStatusCodeNestStatus, 0, 1) == 1) { + return EFI_DEVICE_ERROR; + } + + if (FeaturePcdGet (PcdStatusCodeUseEfiSerial) || FeaturePcdGet (PcdStatusCodeUseHardSerial)) { + SerialStatusCodeReportWorker ( + CodeType, + Value, + Instance, + CallerId, + Data + ); + } + if (FeaturePcdGet (PcdStatusCodeUseRuntimeMemory)) { + RtMemoryStatusCodeReportWorker ( + CodeType, + Value, + Instance + ); + } + if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { + DataHubStatusCodeReportWorker ( + CodeType, + Value, + Instance, + CallerId, + Data + ); + } + if (FeaturePcdGet (PcdStatusCodeUseOEM)) { + // + // Call OEM hook status code library API to report status code to OEM device + // + OemHookStatusCodeReport ( + CodeType, + Value, + Instance, + CallerId, + Data + ); + } + + // + // Restore the nest status of report + // + InterlockedCompareExchange32 (&mStatusCodeNestStatus, 1, 0); + + return EFI_SUCCESS; +} + + +/** + Virtual address change notification call back. It converts global pointer + to virtual address. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, which is + always zero in current implementation. + +**/ +VOID +EFIAPI +VirtualAddressChangeCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // Convert memory status code table to virtual address; + // + EfiConvertPointer ( + 0, + (VOID **) &mRtMemoryStatusCodeTable + ); +} + +/** + Dispatch initialization request to sub status code devices based on + customized feature flags. + +**/ +VOID +InitializationDispatcherWorker ( + VOID + ) +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_STATUS Status; + MEMORY_STATUSCODE_PACKET_HEADER *PacketHeader; + MEMORY_STATUSCODE_RECORD *Record; + UINTN ExpectedPacketIndex; + UINTN Index; + VOID *HobStart; + + // + // If enable UseSerial, then initialize serial port. + // if enable UseRuntimeMemory, then initialize runtime memory status code worker. + // if enable UseDataHub, then initialize data hub status code worker. + // + if (FeaturePcdGet (PcdStatusCodeUseEfiSerial)) { + Status = EfiSerialStatusCodeInitializeWorker (); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseHardSerial)) { + // + // Call Serial Port Lib API to initialize serial port. + // + Status = SerialPortInitialize (); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseRuntimeMemory)) { + Status = RtMemoryStatusCodeInitializeWorker (); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { + Status = DataHubStatusCodeInitializeWorker (); + ASSERT_EFI_ERROR (Status); + } + if (FeaturePcdGet (PcdStatusCodeUseOEM)) { + // + // Call OEM hook status code library API to initialize OEM device for status code. + // + Status = OemHookStatusCodeInitialize (); + ASSERT_EFI_ERROR (Status); + } + + // + // Replay Status code which saved in GUID'ed HOB to all supported devices. + // + + // + // Journal GUID'ed HOBs to find all record entry, if found, + // then output record to support replay device. + // + ExpectedPacketIndex = 0; + Hob.Raw = GetFirstGuidHob (&gMemoryStatusCodeRecordGuid); + HobStart = Hob.Raw; + while (Hob.Raw != NULL) { + PacketHeader = (MEMORY_STATUSCODE_PACKET_HEADER *) GET_GUID_HOB_DATA (Hob.Guid); + if (PacketHeader->PacketIndex == ExpectedPacketIndex) { + Record = (MEMORY_STATUSCODE_RECORD *) (PacketHeader + 1); + for (Index = 0; Index < PacketHeader->RecordIndex; Index++) { + // + // Dispatch records to devices based on feature flag. + // + if (FeaturePcdGet (PcdStatusCodeReplayInSerial) && + (FeaturePcdGet (PcdStatusCodeUseHardSerial) || + FeaturePcdGet (PcdStatusCodeUseEfiSerial))) { + SerialStatusCodeReportWorker ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance, + NULL, + NULL + ); + } + if (FeaturePcdGet (PcdStatusCodeReplayInRuntimeMemory) && + FeaturePcdGet (PcdStatusCodeUseRuntimeMemory)) { + RtMemoryStatusCodeReportWorker ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance + ); + } + if (FeaturePcdGet (PcdStatusCodeReplayInDataHub) && + FeaturePcdGet (PcdStatusCodeUseDataHub)) { + DataHubStatusCodeReportWorker ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance, + NULL, + NULL + ); + } + if (FeaturePcdGet (PcdStatusCodeReplayInOEM) && + FeaturePcdGet (PcdStatusCodeUseOEM)) { + // + // Call OEM hook status code library API to report status code to OEM device + // + OemHookStatusCodeReport ( + Record[Index].CodeType, + Record[Index].Value, + Record[Index].Instance, + NULL, + NULL + ); + } + } + ExpectedPacketIndex++; + + // + // See whether there is gap of packet or not + // + if (HobStart != NULL) { + HobStart = NULL; + Hob.Raw = HobStart; + continue; + } + } else if (HobStart != NULL) { + // + // Cache the found packet for improve the performance + // + HobStart = Hob.Raw; + } + + Hob.Raw = GetNextGuidHob (&gMemoryStatusCodeRecordGuid, Hob.Raw); + } +} diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h new file mode 100644 index 0000000000..dbf356b53b --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.h @@ -0,0 +1,241 @@ +/** @file + Internal include file of Status Code Runtime DXE Driver. + + Copyright (c) 2006 - 2009, Intel Corporation + 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. + +**/ + +#ifndef __STATUS_CODE_RUNTIME_DXE_H__ +#define __STATUS_CODE_RUNTIME_DXE_H__ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Data hub worker definition +// +#define DATAHUB_STATUS_CODE_SIGNATURE SIGNATURE_32 ('B', 'D', 'H', 'S') + +typedef struct { + UINTN Signature; + LIST_ENTRY Node; + UINT8 Data[sizeof(DATA_HUB_STATUS_CODE_DATA_RECORD) + EFI_STATUS_CODE_DATA_MAX_SIZE]; +} DATAHUB_STATUSCODE_RECORD; + + +// +// Runtime memory status code worker definition +// +typedef struct { + UINT32 RecordIndex; + UINT32 NumberOfRecords; + UINT32 MaxRecordsNumber; +} RUNTIME_MEMORY_STATUSCODE_HEADER; + +extern RUNTIME_MEMORY_STATUSCODE_HEADER *mRtMemoryStatusCodeTable; + +/** + Report status code to all supported device. + + This function implements EFI_STATUS_CODE_PROTOCOL.ReportStatusCode(). + It calls into the workers which dispatches the platform specific listeners. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully + @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. + +**/ +EFI_STATUS +EFIAPI +ReportDispatcher ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + Dispatch initialization request to sub status code devices based on + customized feature flags. + +**/ +VOID +InitializationDispatcherWorker ( + VOID + ); + + +/** + Locates Serial I/O Protocol as initialization for serial status code worker. + + @retval EFI_SUCCESS Serial I/O Protocol is successfully located. + +**/ +EFI_STATUS +EfiSerialStatusCodeInitializeWorker ( + VOID + ); + + +/** + Convert status code value and extended data to readable ASCII string, send string to serial I/O device. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS Status code reported to serial I/O successfully. + @retval EFI_DEVICE_ERROR EFI serial device cannot work after ExitBootService() is called. + @retval EFI_DEVICE_ERROR EFI serial device cannot work with TPL higher than TPL_CALLBACK. + +**/ +EFI_STATUS +SerialStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + Initialize runtime memory status code table as initialization for runtime memory status code worker + + @retval EFI_SUCCESS Runtime memory status code table successfully initialized. + +**/ +EFI_STATUS +RtMemoryStatusCodeInitializeWorker ( + VOID + ); + +/** + Report status code into runtime memory. If the runtime pool is full, roll back to the + first record and overwrite it. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + + @retval EFI_SUCCESS Status code successfully recorded in runtime memory status code table. + +**/ +EFI_STATUS +RtMemoryStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance + ); + +/** + Locate Data Hub Protocol and create event for logging data + as initialization for data hub status code worker. + + @retval EFI_SUCCESS Initialization is successful. + +**/ +EFI_STATUS +DataHubStatusCodeInitializeWorker ( + VOID + ); + + +/** + Report status code into DataHub. + + @param CodeType Indicates the type of status code being reported. + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_DEVICE_ERROR Function is reentered. + @retval EFI_DEVICE_ERROR Function is called at runtime. + @retval EFI_OUT_OF_RESOURCES Fail to allocate memory for free record buffer. + +**/ +EFI_STATUS +DataHubStatusCodeReportWorker ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + + +/** + Virtual address change notification call back. It converts global pointer + to virtual address. + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function's context, which is + always zero in current implementation. + +**/ +VOID +EFIAPI +VirtualAddressChangeCallBack ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +#endif diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf new file mode 100644 index 0000000000..1163ff75ae --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf @@ -0,0 +1,93 @@ +#/** @file +# Status Code Runtime Dxe driver that supports multiple devices and produces +# Status Code Runtime Protocol. +# +# Copyright (c) 2006 - 2009, Intel Corporation. +# +# 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. +# +# +#**/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = StatusCodeRuntimeDxe + FILE_GUID = FEDE0A1B-BCA2-4A9F-BB2B-D9FD7DEC2E9F + MODULE_TYPE = DXE_RUNTIME_DRIVER + VERSION_STRING = 1.0 + EFI_SPECIFICATION_VERSION = 0x00020000 + ENTRY_POINT = StatusCodeRuntimeDxeEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 EBC +# +# VIRTUAL_ADDRESS_MAP_CALLBACK = VirtualAddressChangeCallBack +# + +[Sources.common] + SerialStatusCodeWorker.c + RtMemoryStatusCodeWorker.c + DataHubStatusCodeWorker.c + StatusCodeRuntimeDxe.h + StatusCodeRuntimeDxe.c + +[Packages] + MdePkg/MdePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + OemHookStatusCodeLib + SerialPortLib + UefiRuntimeLib + MemoryAllocationLib + UefiLib + UefiBootServicesTableLib + UefiDriverEntryPoint + HobLib + PcdLib + PrintLib + ReportStatusCodeLib + DebugLib + BaseMemoryLib + BaseLib + SynchronizationLib + + +[Guids] + gEfiDataHubStatusCodeRecordGuid ## SOMETIMES_CONSUMES (Needed if Data Hub is supported for status code.) + gEfiStatusCodeDataTypeDebugGuid ## SOMETIMES_CONSUMES (Needed if Data Hub is supported for status code.) + gMemoryStatusCodeRecordGuid ## CONSUMES ## HOB + gEfiEventVirtualAddressChangeGuid ## CONSUMES ## Event + + +[Protocols] + gEfiStatusCodeRuntimeProtocolGuid ## PRODUCES + gEfiDataHubProtocolGuid ## SOMETIMES_CONSUMES (Needed if Data Hub is supported for status code.) + gEfiSerialIoProtocolGuid ## SOMETIMES_CONSUMES (Needed if Serial is supported for status code.) + + +[FeaturePcd.common] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeReplayInOEM + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeReplayInRuntimeMemory + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeReplayInDataHub + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeReplayInSerial + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseOEM + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseRuntimeMemory + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseEfiSerial + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseHardSerial + + +[Pcd.common] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeRuntimeMemorySize + +[Depex] + TRUE \ No newline at end of file -- cgit v1.2.3