3 Copyright (c) 2004 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 This implements a status code listener that logs status codes into the data
19 hub. This is only active during non-runtime DXE.
20 The status codes are recorded in a extensiable buffer, and a event is signalled
21 to log them to the data hub. The recorder is the producer of the status code in
22 buffer and the event notify function the consummer.
26 #include "BsDataHubStatusCode.h"
29 // Initialize FIFO to cache records.
31 STATIC EFI_LIST_ENTRY mRecordsFifo
= INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo
);
32 STATIC EFI_LIST_ENTRY mRecordsBuffer
= INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer
);
33 STATIC EFI_EVENT mLogDataHubEvent
;
34 STATIC BOOLEAN mEventHandlerActive
= FALSE
;
37 // Cache data hub protocol.
39 STATIC EFI_DATA_HUB_PROTOCOL
*mDataHubProtocol
;
42 DATA_HUB_STATUS_CODE_DATA_RECORD
*
50 Return one DATAHUB_STATUSCODE_RECORD space.
51 The size of free record pool would be extend, if the pool is empty.
59 A pointer to the new allocated node or NULL if non available
63 DATAHUB_STATUSCODE_RECORD
*Record
;
69 CurrentTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
71 if (!IsListEmpty (&mRecordsBuffer
)) {
72 Node
= GetFirstNode (&mRecordsBuffer
);
73 RemoveEntryList (Node
);
75 Record
= _CR (Node
, DATAHUB_STATUSCODE_RECORD
, Node
);
77 if (CurrentTpl
> EFI_TPL_NOTIFY
) {
78 gBS
->RestoreTPL (CurrentTpl
);
82 gBS
->RestoreTPL (CurrentTpl
);
84 gBS
->AllocatePool (EfiBootServicesData
, sizeof (DATAHUB_STATUSCODE_RECORD
) * 16, (VOID
**) &Record
);
88 EfiCommonLibZeroMem (Record
, sizeof (DATAHUB_STATUSCODE_RECORD
) * 16);
91 CurrentTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
92 for (Index
= 1; Index
< 16; Index
++) {
93 InsertTailList (&mRecordsBuffer
, &Record
[Index
].Node
);
97 Record
->Signature
= BS_DATA_HUB_STATUS_CODE_SIGNATURE
;
98 InsertTailList (&mRecordsFifo
, &Record
->Node
);
100 gBS
->RestoreTPL (CurrentTpl
);
102 return (DATA_HUB_STATUS_CODE_DATA_RECORD
*) (Record
->Data
);
106 DATA_HUB_STATUS_CODE_DATA_RECORD
*
114 Retrieve one record from Records FIFO. The record would be removed from FIFO and
115 release to free record buffer.
123 Point to record which is ready to be logged, or NULL if the FIFO of record is empty.
127 DATA_HUB_STATUS_CODE_DATA_RECORD
*RecordData
;
128 DATAHUB_STATUSCODE_RECORD
*Record
;
129 EFI_LIST_ENTRY
*Node
;
134 CurrentTpl
= gBS
->RaiseTPL (EFI_TPL_HIGH_LEVEL
);
136 if (!IsListEmpty (&mRecordsFifo
)) {
137 Node
= GetFirstNode (&mRecordsFifo
);
138 Record
= CR (Node
, DATAHUB_STATUSCODE_RECORD
, Node
, BS_DATA_HUB_STATUS_CODE_SIGNATURE
);
140 RemoveEntryList (&Record
->Node
);
141 InsertTailList (&mRecordsBuffer
, &Record
->Node
);
142 Record
->Signature
= 0;
143 RecordData
= (DATA_HUB_STATUS_CODE_DATA_RECORD
*) Record
->Data
;
146 gBS
->RestoreTPL (CurrentTpl
);
153 BsDataHubReportStatusCode (
154 IN EFI_STATUS_CODE_TYPE CodeType
,
155 IN EFI_STATUS_CODE_VALUE Value
,
157 IN EFI_GUID
* CallerId
,
158 IN EFI_STATUS_CODE_DATA
* Data OPTIONAL
164 Boot service report status code listener. This function logs the status code
169 Same as gRT->ReportStatusCode (See Tiano Runtime Specification)
177 DATA_HUB_STATUS_CODE_DATA_RECORD
*Record
;
181 CHAR16 FormatBuffer
[BYTES_PER_RECORD
];
185 // See whether in runtime phase or not.
187 if (EfiAtRuntime ()) {
189 // For now all we do is post code at runtime
195 // Discard new DataHubRecord caused by DataHub->LogData()
197 if (mEventHandlerActive
) {
201 Record
= AcquireRecordBuffer ();
202 if (Record
== NULL
) {
204 // There are no empty record buffer in private buffers
206 return EFI_OUT_OF_RESOURCES
;
209 // Construct Data Hub Extended Data
211 Record
->CodeType
= CodeType
;
212 Record
->Value
= Value
;
213 Record
->Instance
= Instance
;
215 if (CallerId
!= NULL
) {
216 EfiCopyMem (&Record
->CallerId
, CallerId
, sizeof (EFI_GUID
));
220 if (ReportStatusCodeExtractDebugInfo (Data
, &ErrorLevel
, &Marker
, &Format
)) {
222 // Convert Ascii Format string to Unicode.
224 for (Index
= 0; Format
[Index
] != '\0' && Index
< (BYTES_PER_RECORD
- 1); Index
+= 1) {
225 FormatBuffer
[Index
] = (CHAR16
) Format
[Index
];
228 FormatBuffer
[Index
] = L
'\0';
231 // Put processed string into the buffer
234 (CHAR16
*) (Record
+ 1),
235 BYTES_PER_RECORD
- (sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD
)),
240 EfiCopyMem (&Record
->Data
.Type
, &gEfiStatusCodeDataTypeDebugGuid
, sizeof (EFI_GUID
));
241 Record
->Data
.HeaderSize
= Data
->HeaderSize
;
242 Record
->Data
.Size
= (UINT16
) (Index
* sizeof (CHAR16
));
245 // Copy status code data header
247 EfiCopyMem (&Record
->Data
, Data
, sizeof (EFI_STATUS_CODE_DATA
));
249 if (Data
->Size
> BYTES_PER_RECORD
- sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD
)) {
250 Record
->Data
.Size
= (UINT16
) (BYTES_PER_RECORD
- sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD
));
252 EfiCopyMem ((VOID
*) (Record
+ 1), Data
+ 1, Record
->Data
.Size
);
256 gBS
->SignalEvent (mLogDataHubEvent
);
263 LogDataHubEventHandler (
271 The Event handler which will be notified to log data in Data Hub.
275 Event - Instance of the EFI_EVENT to signal whenever data is
276 available to be logged in the system.
277 Context - Context of the event.
285 DATA_HUB_STATUS_CODE_DATA_RECORD
*Record
;
287 UINT64 DataRecordClass
;
290 // Set global flag so we don't recurse if DataHub->LogData eventually causes new DataHubRecord
292 mEventHandlerActive
= TRUE
;
295 // Log DataRecord in Data Hub.
296 // Journal records fifo to find all record entry.
299 Record
= RetrieveRecord ();
300 if (Record
== NULL
) {
304 // Add in the size of the header we added.
306 Size
= sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD
) + (UINT32
) Record
->Data
.Size
;
308 if ((Record
->CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_PROGRESS_CODE
) {
309 DataRecordClass
= EFI_DATA_RECORD_CLASS_PROGRESS_CODE
;
310 } else if ((Record
->CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_ERROR_CODE
) {
311 DataRecordClass
= EFI_DATA_RECORD_CLASS_ERROR
;
312 } else if ((Record
->CodeType
& EFI_STATUS_CODE_TYPE_MASK
) == EFI_DEBUG_CODE
) {
313 DataRecordClass
= EFI_DATA_RECORD_CLASS_DEBUG
;
316 // Should never get here.
318 DataRecordClass
= EFI_DATA_RECORD_CLASS_DEBUG
|
319 EFI_DATA_RECORD_CLASS_ERROR
|
320 EFI_DATA_RECORD_CLASS_DATA
|
321 EFI_DATA_RECORD_CLASS_PROGRESS_CODE
;
325 // Log DataRecord in Data Hub
328 mDataHubProtocol
->LogData (
331 &gEfiStatusCodeRuntimeProtocolGuid
,
339 mEventHandlerActive
= FALSE
;
345 BsDataHubInitializeStatusCode (
346 IN EFI_HANDLE ImageHandle
,
347 IN EFI_SYSTEM_TABLE
*SystemTable
353 Install a data hub listener.
357 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)
361 EFI_SUCCESS - Logging Hub protocol installed
362 Other - No protocol installed, unload driver.
368 Status
= gBS
->LocateProtocol (
369 &gEfiDataHubProtocolGuid
,
371 (VOID
**) &mDataHubProtocol
373 ASSERT_EFI_ERROR (Status
);
376 // Create a Notify Event to log data in Data Hub
378 Status
= gBS
->CreateEvent (
379 EFI_EVENT_NOTIFY_SIGNAL
,
381 LogDataHubEventHandler
,
386 ASSERT_EFI_ERROR (Status
);