]> git.proxmox.com Git - mirror_edk2.git/blame - EdkCompatibilityPkg/Sample/Platform/Generic/RuntimeDxe/StatusCode/Lib/BsDataHubStatusCode/BsDataHubStatusCode.c
Update the copyright notice format
[mirror_edk2.git] / EdkCompatibilityPkg / Sample / Platform / Generic / RuntimeDxe / StatusCode / Lib / BsDataHubStatusCode / BsDataHubStatusCode.c
CommitLineData
b38907a6 1/*++\r
2\r
4b1e1121
HT
3Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>\r
4This program and the accompanying materials \r
b38907a6 5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13\r
14 BsDataHubStatusCode.c\r
15\r
16Abstract:\r
17\r
18 This implements a status code listener that logs status codes into the data\r
19 hub. This is only active during non-runtime DXE.\r
20 The status codes are recorded in a extensiable buffer, and a event is signalled \r
21 to log them to the data hub. The recorder is the producer of the status code in\r
22 buffer and the event notify function the consummer.\r
23\r
24--*/\r
25\r
26#include "BsDataHubStatusCode.h"\r
27\r
28//\r
95d675b5 29// Initialize FIFO to cache records.\r
b38907a6 30//\r
95d675b5 31STATIC EFI_LIST_ENTRY mRecordsFifo = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsFifo);\r
32STATIC EFI_LIST_ENTRY mRecordsBuffer = INITIALIZE_LIST_HEAD_VARIABLE (mRecordsBuffer);\r
33STATIC EFI_EVENT mLogDataHubEvent;\r
34STATIC BOOLEAN mEventHandlerActive = FALSE;\r
b38907a6 35\r
95d675b5 36//\r
37// Cache data hub protocol.\r
38//\r
39STATIC EFI_DATA_HUB_PROTOCOL *mDataHubProtocol;\r
b38907a6 40\r
95d675b5 41STATIC\r
42DATA_HUB_STATUS_CODE_DATA_RECORD *\r
43AcquireRecordBuffer (\r
b38907a6 44 VOID\r
45 )\r
46/*++\r
47\r
48Routine Description:\r
49\r
95d675b5 50 Return one DATAHUB_STATUSCODE_RECORD space.\r
51 The size of free record pool would be extend, if the pool is empty.\r
b38907a6 52\r
53Arguments:\r
54\r
55 None\r
56\r
57Returns:\r
58\r
59 A pointer to the new allocated node or NULL if non available\r
60\r
61--*/\r
62{\r
95d675b5 63 DATAHUB_STATUSCODE_RECORD *Record;\r
64 EFI_TPL CurrentTpl;\r
65 EFI_LIST_ENTRY *Node;\r
66 UINT32 Index;\r
b38907a6 67\r
95d675b5 68 Record = NULL;\r
69 CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);\r
b38907a6 70\r
95d675b5 71 if (!IsListEmpty (&mRecordsBuffer)) {\r
72 Node = GetFirstNode (&mRecordsBuffer);\r
73 RemoveEntryList (Node);\r
b38907a6 74\r
95d675b5 75 Record = _CR (Node, DATAHUB_STATUSCODE_RECORD, Node);\r
76 } else {\r
77 if (CurrentTpl > EFI_TPL_NOTIFY) {\r
78 gBS->RestoreTPL (CurrentTpl);\r
79 return NULL;\r
b38907a6 80 }\r
b38907a6 81\r
95d675b5 82 gBS->RestoreTPL (CurrentTpl);\r
83 \r
1ebee493 84 gBS->AllocatePool (EfiBootServicesData, sizeof (DATAHUB_STATUSCODE_RECORD) * 16, (VOID **) &Record);\r
95d675b5 85 if (Record == NULL) {\r
b38907a6 86 return NULL;\r
87 }\r
95d675b5 88 EfiCommonLibZeroMem (Record, sizeof (DATAHUB_STATUSCODE_RECORD) * 16); \r
89\r
90\r
91 CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);\r
92 for (Index = 1; Index < 16; Index++) {\r
93 InsertTailList (&mRecordsBuffer, &Record[Index].Node);\r
b38907a6 94 }\r
b38907a6 95 }\r
96\r
95d675b5 97 Record->Signature = BS_DATA_HUB_STATUS_CODE_SIGNATURE;\r
98 InsertTailList (&mRecordsFifo, &Record->Node);\r
99\r
100 gBS->RestoreTPL (CurrentTpl);\r
101\r
102 return (DATA_HUB_STATUS_CODE_DATA_RECORD *) (Record->Data);\r
b38907a6 103}\r
104\r
95d675b5 105STATIC\r
106DATA_HUB_STATUS_CODE_DATA_RECORD *\r
107RetrieveRecord (\r
108 VOID\r
b38907a6 109 )\r
110/*++\r
111\r
112Routine Description:\r
113\r
95d675b5 114 Retrieve one record from Records FIFO. The record would be removed from FIFO and \r
115 release to free record buffer.\r
b38907a6 116\r
117Arguments:\r
118\r
95d675b5 119 None\r
b38907a6 120\r
121Returns:\r
122\r
95d675b5 123 Point to record which is ready to be logged, or NULL if the FIFO of record is empty.\r
b38907a6 124\r
95d675b5 125--*/ \r
b38907a6 126{\r
95d675b5 127 DATA_HUB_STATUS_CODE_DATA_RECORD *RecordData;\r
128 DATAHUB_STATUSCODE_RECORD *Record;\r
129 EFI_LIST_ENTRY *Node;\r
130 EFI_TPL CurrentTpl;\r
131 \r
132 RecordData = NULL;\r
133 \r
134 CurrentTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);\r
b38907a6 135\r
95d675b5 136 if (!IsListEmpty (&mRecordsFifo)) {\r
137 Node = GetFirstNode (&mRecordsFifo);\r
138 Record = CR (Node, DATAHUB_STATUSCODE_RECORD, Node, BS_DATA_HUB_STATUS_CODE_SIGNATURE);\r
139\r
140 RemoveEntryList (&Record->Node);\r
141 InsertTailList (&mRecordsBuffer, &Record->Node);\r
142 Record->Signature = 0;\r
143 RecordData = (DATA_HUB_STATUS_CODE_DATA_RECORD *) Record->Data;\r
b38907a6 144 }\r
145\r
95d675b5 146 gBS->RestoreTPL (CurrentTpl);\r
147\r
148 return RecordData;\r
b38907a6 149}\r
150\r
b38907a6 151EFI_STATUS\r
152EFIAPI\r
153BsDataHubReportStatusCode (\r
154 IN EFI_STATUS_CODE_TYPE CodeType,\r
155 IN EFI_STATUS_CODE_VALUE Value,\r
156 IN UINT32 Instance,\r
157 IN EFI_GUID * CallerId,\r
158 IN EFI_STATUS_CODE_DATA * Data OPTIONAL\r
159 )\r
160/*++\r
161\r
162Routine Description:\r
163\r
164 Boot service report status code listener. This function logs the status code\r
165 into the data hub.\r
166\r
167Arguments:\r
168\r
169 Same as gRT->ReportStatusCode (See Tiano Runtime Specification)\r
170\r
171Returns:\r
172\r
173 None\r
174\r
175--*/\r
176{\r
95d675b5 177 DATA_HUB_STATUS_CODE_DATA_RECORD *Record;\r
178 UINT32 ErrorLevel;\r
179 VA_LIST Marker;\r
180 CHAR8 *Format;\r
181 CHAR16 FormatBuffer[BYTES_PER_RECORD];\r
182 UINTN Index;\r
b38907a6 183\r
95d675b5 184 //\r
185 // See whether in runtime phase or not.\r
186 //\r
b38907a6 187 if (EfiAtRuntime ()) {\r
188 //\r
189 // For now all we do is post code at runtime\r
190 //\r
191 return EFI_SUCCESS;\r
192 }\r
95d675b5 193\r
b38907a6 194 //\r
95d675b5 195 // Discard new DataHubRecord caused by DataHub->LogData()\r
b38907a6 196 //\r
197 if (mEventHandlerActive) {\r
198 return EFI_SUCCESS;\r
199 }\r
200\r
95d675b5 201 Record = AcquireRecordBuffer ();\r
202 if (Record == NULL) {\r
b38907a6 203 //\r
204 // There are no empty record buffer in private buffers\r
205 //\r
206 return EFI_OUT_OF_RESOURCES;\r
207 }\r
208 //\r
209 // Construct Data Hub Extended Data\r
210 //\r
95d675b5 211 Record->CodeType = CodeType;\r
212 Record->Value = Value;\r
213 Record->Instance = Instance;\r
b38907a6 214\r
215 if (CallerId != NULL) {\r
95d675b5 216 EfiCopyMem (&Record->CallerId, CallerId, sizeof (EFI_GUID));\r
b38907a6 217 }\r
218\r
95d675b5 219 if (Data != NULL) {\r
b38907a6 220 if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) {\r
221 //\r
222 // Convert Ascii Format string to Unicode.\r
223 //\r
224 for (Index = 0; Format[Index] != '\0' && Index < (BYTES_PER_RECORD - 1); Index += 1) {\r
225 FormatBuffer[Index] = (CHAR16) Format[Index];\r
226 }\r
227\r
228 FormatBuffer[Index] = L'\0';\r
229\r
230 //\r
231 // Put processed string into the buffer\r
232 //\r
233 Index = VSPrint (\r
95d675b5 234 (CHAR16 *) (Record + 1),\r
b38907a6 235 BYTES_PER_RECORD - (sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD)),\r
236 FormatBuffer,\r
237 Marker\r
238 );\r
95d675b5 239 \r
240 EfiCopyMem (&Record->Data.Type, &gEfiStatusCodeDataTypeDebugGuid, sizeof (EFI_GUID));\r
241 Record->Data.HeaderSize = Data->HeaderSize;\r
242 Record->Data.Size = (UINT16) (Index * sizeof (CHAR16));\r
b38907a6 243 } else {\r
244 //\r
95d675b5 245 // Copy status code data header\r
b38907a6 246 //\r
95d675b5 247 EfiCopyMem (&Record->Data, Data, sizeof (EFI_STATUS_CODE_DATA));\r
b38907a6 248\r
95d675b5 249 if (Data->Size > BYTES_PER_RECORD - sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD)) {\r
250 Record->Data.Size = (UINT16) (BYTES_PER_RECORD - sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD));\r
251 } \r
252 EfiCopyMem ((VOID *) (Record + 1), Data + 1, Record->Data.Size);\r
b38907a6 253 }\r
254 }\r
255\r
256 gBS->SignalEvent (mLogDataHubEvent);\r
257\r
258 return EFI_SUCCESS;\r
259}\r
260\r
261VOID\r
262EFIAPI\r
263LogDataHubEventHandler (\r
264 IN EFI_EVENT Event,\r
265 IN VOID *Context\r
266 )\r
267/*++\r
268\r
269Routine Description:\r
270\r
271 The Event handler which will be notified to log data in Data Hub.\r
272\r
273Arguments:\r
274\r
275 Event - Instance of the EFI_EVENT to signal whenever data is\r
276 available to be logged in the system.\r
277 Context - Context of the event.\r
278\r
279Returns:\r
280\r
281 None.\r
282\r
283--*/\r
284{\r
95d675b5 285 DATA_HUB_STATUS_CODE_DATA_RECORD *Record;\r
286 UINT32 Size;\r
b38907a6 287 UINT64 DataRecordClass;\r
b38907a6 288\r
289 //\r
95d675b5 290 // Set global flag so we don't recurse if DataHub->LogData eventually causes new DataHubRecord\r
b38907a6 291 //\r
292 mEventHandlerActive = TRUE;\r
293 \r
294 //\r
295 // Log DataRecord in Data Hub.\r
95d675b5 296 // Journal records fifo to find all record entry.\r
b38907a6 297 //\r
95d675b5 298 while (1) {\r
299 Record = RetrieveRecord ();\r
300 if (Record == NULL) {\r
301 break;\r
302 }\r
b38907a6 303 //\r
304 // Add in the size of the header we added.\r
305 //\r
95d675b5 306 Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + (UINT32) Record->Data.Size;\r
b38907a6 307\r
95d675b5 308 if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) {\r
b38907a6 309 DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE;\r
95d675b5 310 } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) {\r
b38907a6 311 DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR;\r
95d675b5 312 } else if ((Record->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) {\r
b38907a6 313 DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG;\r
314 } else {\r
315 //\r
316 // Should never get here.\r
317 //\r
318 DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG |\r
319 EFI_DATA_RECORD_CLASS_ERROR |\r
320 EFI_DATA_RECORD_CLASS_DATA |\r
321 EFI_DATA_RECORD_CLASS_PROGRESS_CODE;\r
322 }\r
323\r
95d675b5 324 //\r
325 // Log DataRecord in Data Hub\r
326 //\r
327 \r
328 mDataHubProtocol->LogData (\r
329 mDataHubProtocol,\r
330 &gEfiStatusCodeGuid,\r
331 &gEfiStatusCodeRuntimeProtocolGuid,\r
332 DataRecordClass,\r
333 Record,\r
334 Size\r
335 );\r
b38907a6 336\r
b38907a6 337 }\r
338\r
339 mEventHandlerActive = FALSE;\r
340\r
b38907a6 341}\r
342\r
b38907a6 343EFI_STATUS\r
95d675b5 344EFIAPI\r
b38907a6 345BsDataHubInitializeStatusCode (\r
346 IN EFI_HANDLE ImageHandle,\r
347 IN EFI_SYSTEM_TABLE *SystemTable\r
348 )\r
349/*++\r
350\r
351Routine Description:\r
352\r
353 Install a data hub listener.\r
354\r
355Arguments:\r
356\r
357 (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT)\r
358\r
359Returns:\r
360\r
361 EFI_SUCCESS - Logging Hub protocol installed\r
362 Other - No protocol installed, unload driver.\r
363\r
364--*/\r
365{\r
366 EFI_STATUS Status;\r
b38907a6 367\r
95d675b5 368 Status = gBS->LocateProtocol (\r
369 &gEfiDataHubProtocolGuid, \r
370 NULL, \r
371 (VOID **) &mDataHubProtocol\r
372 );\r
b38907a6 373 ASSERT_EFI_ERROR (Status);\r
374\r
b38907a6 375 //\r
376 // Create a Notify Event to log data in Data Hub\r
377 //\r
378 Status = gBS->CreateEvent (\r
379 EFI_EVENT_NOTIFY_SIGNAL,\r
380 EFI_TPL_CALLBACK,\r
381 LogDataHubEventHandler,\r
382 NULL,\r
383 &mLogDataHubEvent\r
384 );\r
385\r
95d675b5 386 ASSERT_EFI_ERROR (Status);\r
387\r
b38907a6 388 return EFI_SUCCESS;\r
389}\r
95d675b5 390\r
391\r