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