From 28a94112d1dda45eaf8336febf5c208686de8c1e Mon Sep 17 00:00:00 2001 From: xli24 Date: Fri, 13 Aug 2010 05:43:30 +0000 Subject: [PATCH] Add datahub status sode handler driver. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10795 6f19259b-4bc3-4df7-8a09-765794883524 --- .../IntelFrameworkModulePkg.dsc | 3 +- .../DataHubStatusCodeWorker.c | 375 ++++++++++++++++++ .../DatahubStatusCodeHandlerDxe.c | 88 ++++ .../DatahubStatusCodeHandlerDxe.h | 90 +++++ .../DatahubStatusCodeHandlerDxe.inf | 70 ++++ 5 files changed, 625 insertions(+), 1 deletion(-) create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h create mode 100644 IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf diff --git a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc index 71cd6b094b..8cb6430500 100644 --- a/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc +++ b/IntelFrameworkModulePkg/IntelFrameworkModulePkg.dsc @@ -142,7 +142,8 @@ IntelFrameworkModulePkg/Universal/Console/VgaClassDxe/VgaClassDxe.inf IntelFrameworkModulePkg/Universal/BdsDxe/BdsDxe.inf IntelFrameworkModulePkg/Universal/LegacyRegionDxe/LegacyRegionDxe.inf - + IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf + [Components.IA32] IntelFrameworkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCodeRuntimeDxe.inf IntelFrameworkModulePkg/Universal/CpuIoDxe/CpuIoDxe.inf { diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c new file mode 100644 index 0000000000..cb2cc767eb --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DataHubStatusCodeWorker.c @@ -0,0 +1,375 @@ +/** @file + Data Hub status code worker. + + Copyright (c) 2010, 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 "DatahubStatusCodeHandlerDxe.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 = NULL; + + +/** + 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; + BASE_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; + } + + 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 = UnicodeBSPrintAsciiFormat ( + (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 + ); + if (EFI_ERROR (Status)) { + mDataHubProtocol = NULL; + return 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/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c new file mode 100644 index 0000000000..ee7bdd36af --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.c @@ -0,0 +1,88 @@ +/** @file + Status Code Handler Driver which produces datahub handler and hook it + onto the DXE status code router. + + Copyright (c) 2010, 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 "DatahubStatusCodeHandlerDxe.h" + +EFI_EVENT mExitBootServicesEvent = NULL; +EFI_RSC_HANDLER_PROTOCOL *mRscHandlerProtocol = NULL; + +/** + Unregister status code callback functions only available at boot time from + report status code router when exiting boot services. + + @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 +UnregisterBootTimeHandlers ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + mRscHandlerProtocol->Unregister (DataHubStatusCodeReportWorker); +} + +/** + Entry point of DXE Status Code Driver. + + This function is the entry point of this DXE Status Code Driver. + It initializes registers status code handlers, 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 +DatahubStatusCodeHandlerDxeEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + if (FeaturePcdGet (PcdStatusCodeUseDataHub)) { + Status = gBS->LocateProtocol ( + &gEfiRscHandlerProtocolGuid, + NULL, + (VOID **) &mRscHandlerProtocol + ); + ASSERT_EFI_ERROR (Status); + + // + // Dispatch initialization request to supported devices + // + DataHubStatusCodeInitializeWorker (); + + mRscHandlerProtocol->Register (DataHubStatusCodeReportWorker, TPL_HIGH_LEVEL); + + Status = gBS->CreateEventEx ( + EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + UnregisterBootTimeHandlers, + NULL, + &gEfiEventExitBootServicesGuid, + &mExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); + } + + return EFI_SUCCESS; +} diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h new file mode 100644 index 0000000000..6ee58bb909 --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.h @@ -0,0 +1,90 @@ +/** @file + Internal include file for Datahub Status Code Handler Driver. + + Copyright (c) 2010, 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 __DATAHUB_STATUS_CODE_HANDLER_DXE_H__ +#define __DATAHUB_STATUS_CODE_HANDLER_DXE_H__ + +#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; + +/** + 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 + ); + +/** + 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 + ); + +#endif diff --git a/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf new file mode 100644 index 0000000000..f6f728df2c --- /dev/null +++ b/IntelFrameworkModulePkg/Universal/StatusCode/DatahubStatusCodeHandlerDxe/DatahubStatusCodeHandlerDxe.inf @@ -0,0 +1,70 @@ +## @file +# Status Code Handler Driver which produces datahub handler and hook it +# onto the DXE status code router. +# +# Copyright (c) 2010, 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 = DatahubStatusCodeHandlerDxe + FILE_GUID = 863D214F-0920-437B-8CAD-88EA83A24E97 + MODULE_TYPE = DXE_DRIVER + ENTRY_POINT = DatahubStatusCodeHandlerDxeEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 IPF EBC +# + +[Sources] + DatahubStatusCodeHandlerDxe.h + DatahubStatusCodeHandlerDxe.c + DataHubStatusCodeWorker.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + IntelFrameworkPkg/IntelFrameworkPkg.dec + IntelFrameworkModulePkg/IntelFrameworkModulePkg.dec + +[LibraryClasses] + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + PcdLib + PrintLib + ReportStatusCodeLib + DebugLib + SynchronizationLib + BaseMemoryLib + +[Guids] + gEfiEventExitBootServicesGuid ## CONSUMES ## Event + gEfiStatusCodeDataTypeStringGuid ## CONSUMES + gEfiDataHubStatusCodeRecordGuid ## CONSUMES + gEfiStatusCodeDataTypeDebugGuid ## CONSUMES + +[Protocols] + gEfiRscHandlerProtocolGuid ## CONSUMES + gEfiDataHubProtocolGuid ## CONSUMES + gEfiStatusCodeRuntimeProtocolGuid ## CONSUMES + +[FeaturePcd] + gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdStatusCodeUseDataHub + +[Depex] + gEfiRscHandlerProtocolGuid AND + gEfiDataHubProtocolGuid + \ No newline at end of file -- 2.39.2