]> git.proxmox.com Git - mirror_edk2.git/blob - IntelFrameworkModulePkg/Universal/StatusCode/Dxe/DataHubStatusCodeWorker.c
1) Change the file name of StatusCode.h to DataHubStatusCodeRecord.h
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / StatusCode / Dxe / DataHubStatusCodeWorker.c
1 /** @file
2 Data Hub status code worker in DXE.
3
4 Copyright (c) 2006, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include "DxeStatusCode.h"
16
17 //
18 // Initialize FIFO to cache records.
19 //
20 STATIC
21 LIST_ENTRY mRecordsFifo = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo);
22 STATIC
23 LIST_ENTRY mRecordsBuffer = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer);
24 STATIC
25 EFI_EVENT mLogDataHubEvent;
26 //
27 // Cache data hub protocol.
28 //
29 STATIC
30 EFI_DATA_HUB_PROTOCOL *mDataHubProtocol;
31
32
33 /**
34 Return one DATAHUB_STATUSCODE_RECORD space.
35 The size of free record pool would be extend, if the pool is empty.
36
37
38 @retval NULL Can not allocate free memeory for record.
39 @retval !NULL Point to buffer of record.
40
41 **/
42 STATIC
43 DATA_HUB_STATUS_CODE_DATA_RECORD *
44 AcquireRecordBuffer (
45 VOID
46 )
47 {
48 DATAHUB_STATUSCODE_RECORD *Record;
49 EFI_TPL CurrentTpl;
50 LIST_ENTRY *Node;
51 UINT32 Index;
52
53 CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
54
55 if (!IsListEmpty (&mRecordsBuffer)) {
56 Node = GetFirstNode (&mRecordsBuffer);
57 RemoveEntryList (Node);
58
59 Record = _CR (Node, DATAHUB_STATUSCODE_RECORD, Node);
60 } else {
61 if (CurrentTpl > TPL_NOTIFY) {
62 gBS->RestoreTPL (CurrentTpl);
63 return NULL;
64 }
65
66 gBS->RestoreTPL (CurrentTpl);
67 Record = (DATAHUB_STATUSCODE_RECORD *) AllocateZeroPool (sizeof (DATAHUB_STATUSCODE_RECORD) * 16);
68 if (NULL == Record) {
69 return NULL;
70 }
71
72 CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
73 for (Index = 1; Index < 16; Index++) {
74 InsertTailList (&mRecordsBuffer, &Record[Index].Node);
75 }
76 }
77
78 Record->Signature = DATAHUB_STATUS_CODE_SIGNATURE;
79 InsertTailList (&mRecordsFifo, &Record->Node);
80
81 gBS->RestoreTPL (CurrentTpl);
82
83 return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data);
84 }
85
86
87 /**
88 Retrieve one record from Records FIFO. The record would be removed from FIFO and
89 release to free record buffer.
90
91 @return !NULL Point to record, which is ready to be logged.
92 @return NULL the FIFO of record is empty.
93
94 **/
95 STATIC
96 DATA_HUB_STATUS_CODE_DATA_RECORD *
97 RetrieveRecord (
98 VOID
99 )
100 {
101 DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData = NULL;
102 DATAHUB_STATUSCODE_RECORD *Record;
103 LIST_ENTRY *Node;
104 EFI_TPL CurrentTpl;
105
106 CurrentTpl = gBS->RaiseTPL (TPL_HIGH_LEVEL);
107
108 if (!IsListEmpty (&mRecordsFifo)) {
109 Node = GetFirstNode (&mRecordsFifo);
110 Record = CR (Node, DATAHUB_STATUSCODE_RECORD, Node, DATAHUB_STATUS_CODE_SIGNATURE);
111
112 RemoveEntryList (&Record->Node);
113 InsertTailList (&mRecordsBuffer, &Record->Node);
114 Record->Signature = 0;
115 RecordData = (DATA_HUB_STATUS_CODE_DATA_RECORD *) Record->Data;
116 }
117
118 gBS->RestoreTPL (CurrentTpl);
119
120 return RecordData;
121 }
122
123
124 /**
125 Report status code into DataHub.
126
127 @param CodeType Indicates the type of status code being reported. Type EFI_STATUS_CODE_TYPE is defined in "Related Definitions" below.
128
129 @param Value Describes the current status of a hardware or software entity.
130 This included information about the class and subclass that is used to classify the entity
131 as well as an operation. For progress codes, the operation is the current activity.
132 For error codes, it is the exception. For debug codes, it is not defined at this time.
133 Type EFI_STATUS_CODE_VALUE is defined in "Related Definitions" below.
134 Specific values are discussed in the Intel? Platform Innovation Framework for EFI Status Code Specification.
135
136 @param Instance The enumeration of a hardware or software entity within the system.
137 A system may contain multiple entities that match a class/subclass pairing.
138 The instance differentiates between them. An instance of 0 indicates that instance information is unavailable,
139 not meaningful, or not relevant. Valid instance numbers start with 1.
140
141
142 @param CallerId This optional parameter may be used to identify the caller.
143 This parameter allows the status code driver to apply different rules to different callers.
144 Type EFI_GUID is defined in InstallProtocolInterface() in the EFI 1.10 Specification.
145
146
147 @param Data This optional parameter may be used to pass additional data
148
149 @retval EFI_OUT_OF_RESOURCES Can not acquire record buffer.
150 @retval EFI_DEVICE_ERROR EFI serial device can not work after ExitBootService() is called .
151 @retval EFI_SUCCESS Success to cache status code and signal log data event.
152
153 **/
154 EFI_STATUS
155 DataHubStatusCodeReportWorker (
156 IN EFI_STATUS_CODE_TYPE CodeType,
157 IN EFI_STATUS_CODE_VALUE Value,
158 IN UINT32 Instance,
159 IN EFI_GUID *CallerId,
160 IN EFI_STATUS_CODE_DATA *Data OPTIONAL
161 )
162 {
163 DATA_HUB_STATUS_CODE_DATA_RECORD *Record;
164 UINT32 ErrorLevel;
165 VA_LIST Marker;
166 CHAR8 *Format;
167 UINTN CharCount;
168
169 //
170 // See whether in runtime phase or not.
171 //
172 if (EfiAtRuntime ()) {
173 return EFI_DEVICE_ERROR;
174 }
175
176 Record = AcquireRecordBuffer ();
177 if (Record == NULL) {
178 //
179 // There are no empty record buffer in private buffers
180 //
181 return EFI_OUT_OF_RESOURCES;
182 }
183
184 //
185 // Construct Data Hub Extended Data
186 //
187 Record->CodeType = CodeType;
188 Record->Value = Value;
189 Record->Instance = Instance;
190
191 if (CallerId != NULL) {
192 CopyMem (&Record->CallerId, CallerId, sizeof (EFI_GUID));
193 }
194
195 if (Data != NULL) {
196 if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {
197 CharCount = UnicodeVSPrintAsciiFormat (
198 (CHAR16 *) (Record + 1),
199 EFI_STATUS_CODE_DATA_MAX_SIZE,
200 Format,
201 Marker
202 );
203 //
204 // Change record data type from DebugType to String Type.
205 //
206 CopyGuid (&Record->Data.Type, &gEfiStatusCodeDataTypeDebugGuid);
207 Record->Data.HeaderSize = Data->HeaderSize;
208 Record->Data.Size = (UINT16) ((CharCount + 1) * sizeof (CHAR16));
209 } else {
210 //
211 // Copy status code data header
212 //
213 CopyMem (&Record->Data, Data, sizeof (EFI_STATUS_CODE_DATA));
214
215 if (Data->Size > EFI_STATUS_CODE_DATA_MAX_SIZE) {
216 Record->Data.Size = EFI_STATUS_CODE_DATA_MAX_SIZE;
217 }
218 CopyMem ((VOID *) (Record + 1), Data + 1, Record->Data.Size);
219 }
220 }
221
222 gBS->SignalEvent (mLogDataHubEvent);
223
224 return EFI_SUCCESS;
225 }
226
227
228 /**
229 The Event handler which will be notified to log data in Data Hub.
230
231 @param Event Instance of the EFI_EVENT to signal whenever data is
232 available to be logged in the system.
233 @param Context Context of the event.
234
235 **/
236 STATIC
237 VOID
238 EFIAPI
239 LogDataHubEventCallBack (
240 IN EFI_EVENT Event,
241 IN VOID *Context
242 )
243 {
244 DATA_HUB_STATUS_CODE_DATA_RECORD *Record;
245 UINT32 Size;
246 UINT64 DataRecordClass;
247
248 //
249 // Log DataRecord in Data Hub.
250 // Journal records fifo to find all record entry.
251 //
252 while (1) {
253 Record = RetrieveRecord ();
254 if (Record == NULL) {
255 break;
256 }
257 //
258 // Add in the size of the header we added.
259 //
260 Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + (UINT32) Record->Data.Size;
261
262 if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {
263 DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
264 } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {
265 DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR;
266 } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {
267 DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG;
268 } else {
269 //
270 // Should never get here.
271 //
272 DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG |
273 EFI_DATA_RECORD_CLASS_ERROR |
274 EFI_DATA_RECORD_CLASS_DATA |
275 EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
276 }
277
278 //
279 // Log DataRecord in Data Hub
280 //
281
282 mDataHubProtocol->LogData (
283 mDataHubProtocol,
284 &gEfiDataHubStatusCodeRecordGuid,
285 &gEfiStatusCodeRuntimeProtocolGuid,
286 DataRecordClass,
287 Record,
288 Size
289 );
290
291 }
292 }
293
294
295 /**
296 Initialize data hubstatus code.
297 Create a data hub listener.
298
299 @return The function always return EFI_SUCCESS
300
301 **/
302 EFI_STATUS
303 DataHubStatusCodeInitializeWorker (
304 VOID
305 )
306 {
307 EFI_STATUS Status;
308
309 Status = gBS->LocateProtocol (
310 &gEfiDataHubProtocolGuid,
311 NULL,
312 (VOID **) &mDataHubProtocol
313 );
314 ASSERT_EFI_ERROR (Status);
315
316 //
317 // Create a Notify Event to log data in Data Hub
318 //
319 Status = gBS->CreateEvent (
320 EVT_NOTIFY_SIGNAL,
321 TPL_CALLBACK,
322 LogDataHubEventCallBack,
323 NULL,
324 &mLogDataHubEvent
325 );
326
327 ASSERT_EFI_ERROR (Status);
328
329 return EFI_SUCCESS;
330 }
331
332