]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFrameworkModulePkg/Universal/DataHubDxe/DataHub.c
Update code style and comments
[mirror_edk2.git] / IntelFrameworkModulePkg / Universal / DataHubDxe / DataHub.c
CommitLineData
3db51098 1/**@file\r
83f6d1a0 2 This code produces the Data Hub protocol. It preloads the data hub\r
3 with status information copied in from PEI HOBs.\r
4 \r
5 Only code that implements the Data Hub protocol should go in this file!\r
6\r
7 The Term MTC stands for MonoTonicCounter. \r
8\r
9 For more information please look at DataHub.doc\r
10\r
11 NOTE: For extra security of the log GetNextDataRecord () could return a copy\r
12 of the data record.\r
3db51098 13 \r
14Copyright (c) 2006, Intel Corporation \r
15All rights reserved. This program and the accompanying materials \r
16are licensed and made available under the terms and conditions of the BSD License \r
17which accompanies this distribution. The full text of the license may be found at \r
18http://opensource.org/licenses/bsd-license.php \r
19 \r
20THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
21WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
22\r
23**/\r
83f6d1a0 24\r
25#include "DataHub.h"\r
26\r
27CONST EFI_GUID gZeroGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } };\r
28\r
9f6531d1 29//\r
30// Module Global:\r
31// Since this driver will only ever produce one instance of the Logging Hub\r
32// protocol you are not required to dynamically allocate the PrivateData.\r
33//\r
34DATA_HUB_INSTANCE mPrivateData;\r
35\r
83f6d1a0 36//\r
37// Worker functions private to this file\r
38//\r
83f6d1a0 39DATA_HUB_FILTER_DRIVER *\r
40FindFilterDriverByEvent (\r
41 IN LIST_ENTRY *Head,\r
42 IN EFI_EVENT Event\r
43 );\r
44\r
83f6d1a0 45EFI_DATA_RECORD_HEADER *\r
46GetNextDataRecord (\r
47 IN LIST_ENTRY *Head,\r
48 IN UINT64 ClassFilter,\r
49 IN OUT UINT64 *PtrCurrentMTC\r
50 );\r
51\r
a73d0c74 52/**\r
53\r
54 Log data record into the data logging hub\r
55\r
56 @param This - Protocol instance structure\r
57 @param DataRecordGuid - GUID that defines record contents\r
58 @param ProducerName - GUID that defines the name of the producer of the data\r
59 @param DataRecordClass - Class that defines generic record type\r
60 @param RawData - Data Log record as defined by DataRecordGuid\r
61 @param RawDataSize - Size of Data Log data in bytes\r
62\r
63 @retval EFI_SUCCESS - If data was logged\r
64 @retval EFI_OUT_OF_RESOURCES - If data was not logged due to lack of system \r
65 resources.\r
66**/\r
83f6d1a0 67EFI_STATUS\r
68EFIAPI\r
69DataHubLogData (\r
70 IN EFI_DATA_HUB_PROTOCOL *This,\r
71 IN EFI_GUID *DataRecordGuid,\r
72 IN EFI_GUID *ProducerName,\r
73 IN UINT64 DataRecordClass,\r
74 IN VOID *RawData,\r
75 IN UINT32 RawDataSize\r
76 )\r
83f6d1a0 77{\r
78 EFI_STATUS Status;\r
79 DATA_HUB_INSTANCE *Private;\r
80 EFI_DATA_ENTRY *LogEntry;\r
81 UINT32 TotalSize;\r
82 UINT32 RecordSize;\r
83 EFI_DATA_RECORD_HEADER *Record;\r
84 VOID *Raw;\r
85 DATA_HUB_FILTER_DRIVER *FilterEntry;\r
86 LIST_ENTRY *Link;\r
87 LIST_ENTRY *Head;\r
88\r
89 Private = DATA_HUB_INSTANCE_FROM_THIS (This);\r
90\r
91 //\r
92 // Combine the storage for the internal structs and a copy of the log record.\r
93 // Record follows PrivateLogEntry. The consumer will be returned a pointer\r
94 // to Record so we don't what it to be the thing that was allocated from\r
95 // pool, so the consumer can't free an data record by mistake.\r
96 //\r
97 RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize;\r
98 TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize;\r
99\r
100 //\r
101 // The Logging action is the critical section, so it is locked.\r
102 // The MTC asignment & update, time, and logging must be an\r
103 // atomic operation, so use the lock.\r
104 //\r
105 Status = EfiAcquireLockOrFail (&Private->DataLock);\r
106 if (EFI_ERROR (Status)) {\r
107 //\r
108 // Reentrancy detected so exit!\r
109 //\r
110 return Status;\r
111 }\r
112\r
113 LogEntry = AllocatePool (TotalSize);\r
114\r
115 if (LogEntry == NULL) {\r
116 EfiReleaseLock (&Private->DataLock);\r
117 return EFI_OUT_OF_RESOURCES;\r
118 }\r
119\r
120 ZeroMem (LogEntry, TotalSize);\r
121\r
122 Record = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1);\r
123 Raw = (VOID *) (Record + 1);\r
124\r
125 //\r
126 // Build Standard Log Header\r
127 //\r
128 Record->Version = EFI_DATA_RECORD_HEADER_VERSION;\r
129 Record->HeaderSize = sizeof (EFI_DATA_RECORD_HEADER);\r
130 Record->RecordSize = RecordSize;\r
131 CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID));\r
132 CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID));\r
133 Record->DataRecordClass = DataRecordClass;\r
134\r
41e4912f 135 //\r
136 // Ensure LogMonotonicCount is not zero\r
137 //\r
138 Record->LogMonotonicCount = ++Private->GlobalMonotonicCount;\r
83f6d1a0 139\r
140 gRT->GetTime (&Record->LogTime, NULL);\r
141\r
142 //\r
143 // Insert log into the internal linked list.\r
144 //\r
145 LogEntry->Signature = EFI_DATA_ENTRY_SIGNATURE;\r
146 LogEntry->Record = Record;\r
147 LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize;\r
148 InsertTailList (&Private->DataListHead, &LogEntry->Link);\r
149\r
150 CopyMem (Raw, RawData, RawDataSize);\r
151\r
152 EfiReleaseLock (&Private->DataLock);\r
153\r
154 //\r
155 // Send Signal to all the filter drivers which are interested\r
156 // in the record's class and guid.\r
157 //\r
158 Head = &Private->FilterDriverListHead;\r
159 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
160 FilterEntry = FILTER_ENTRY_FROM_LINK (Link);\r
161 if (((FilterEntry->ClassFilter & DataRecordClass) != 0) &&\r
162 (CompareGuid (&FilterEntry->FilterDataRecordGuid, &gZeroGuid) || \r
163 CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) {\r
164 gBS->SignalEvent (FilterEntry->Event);\r
165 }\r
166 }\r
167\r
168 return EFI_SUCCESS;\r
169}\r
170\r
a73d0c74 171/**\r
83f6d1a0 172\r
173 Get a previously logged data record and the MonotonicCount for the next\r
174 availible Record. This allows all records or all records later \r
175 than a give MonotonicCount to be returned. If an optional FilterDriverEvent\r
176 is passed in with a MonotonicCout of zero return the first record \r
177 not yet read by the filter driver. If FilterDriverEvent is NULL and \r
178 MonotonicCount is zero return the first data record.\r
179\r
a73d0c74 180 @param This The EFI_DATA_HUB_PROTOCOL instance.\r
181 @param MonotonicCount Specifies the Record to return. On input, zero means\r
182 return the first record. On output, contains the next\r
183 record to availible. Zero indicates no more records.\r
184 @param FilterDriverEvent If FilterDriverEvent is not passed in a MonotonicCount \r
185 of zero, it means to return the first data record. \r
186 If FilterDriverEvent is passed in, then a MonotonicCount \r
187 of zero means to return the first data not yet read by \r
188 FilterDriverEvent.\r
189 @param Record Returns a dynamically allocated memory buffer with a data \r
190 record that matches MonotonicCount.\r
191\r
192 @retval EFI_SUCCESS - Data was returned in Record.\r
193 @retval EFI_INVALID_PARAMETER - FilterDriverEvent was passed in but does not exist.\r
194 @retval EFI_NOT_FOUND - MonotonicCount does not match any data record in the\r
83f6d1a0 195 system. If a MonotonicCount of zero was passed in, then\r
196 no data records exist in the system.\r
a73d0c74 197 @retval EFI_OUT_OF_RESOURCES - Record was not returned due to lack of system resources.\r
83f6d1a0 198\r
a73d0c74 199**/\r
a73d0c74 200EFI_STATUS\r
201EFIAPI\r
202DataHubGetNextRecord (\r
203 IN EFI_DATA_HUB_PROTOCOL *This,\r
204 IN OUT UINT64 *MonotonicCount,\r
205 IN EFI_EVENT *FilterDriverEvent, OPTIONAL\r
206 OUT EFI_DATA_RECORD_HEADER **Record\r
207 )\r
83f6d1a0 208{\r
209 DATA_HUB_INSTANCE *Private;\r
210 DATA_HUB_FILTER_DRIVER *FilterDriver;\r
211 UINT64 ClassFilter;\r
212 UINT64 FilterMonotonicCount;\r
213\r
214 Private = DATA_HUB_INSTANCE_FROM_THIS (This);\r
215\r
216 FilterDriver = NULL;\r
217 FilterMonotonicCount = 0;\r
218 ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |\r
219 EFI_DATA_RECORD_CLASS_ERROR |\r
220 EFI_DATA_RECORD_CLASS_DATA |\r
221 EFI_DATA_RECORD_CLASS_PROGRESS_CODE;\r
222\r
223 if (FilterDriverEvent != NULL) {\r
224 //\r
225 // For events the beginning is the last unread record. This info is\r
226 // stored in the instance structure, so we must look up the event\r
227 // to get the data.\r
228 //\r
229 FilterDriver = FindFilterDriverByEvent (\r
230 &Private->FilterDriverListHead,\r
231 *FilterDriverEvent\r
232 );\r
233 if (FilterDriver == NULL) {\r
234 return EFI_INVALID_PARAMETER;\r
235 }\r
236 //\r
237 // Use the Class filter the event was created with.\r
238 //\r
239 ClassFilter = FilterDriver->ClassFilter;\r
240\r
241 if (*MonotonicCount == 0) {\r
242 //\r
243 // Use the MTC from the Filter Driver.\r
244 //\r
245 FilterMonotonicCount = FilterDriver->GetNextMonotonicCount;\r
2ebbe08c 246 \r
247 //\r
248 // The GetNextMonotonicCount field remembers the last value from the previous time.\r
249 // But we already processed this vaule, so we need to find the next one.\r
250 //\r
251 *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, &FilterMonotonicCount);\r
83f6d1a0 252 if (FilterMonotonicCount != 0) {\r
2ebbe08c 253 *MonotonicCount = FilterMonotonicCount;\r
254 }\r
255 \r
256 if ((FilterDriver->GetNextMonotonicCount != 0) && (FilterMonotonicCount == 0)) {\r
83f6d1a0 257 //\r
2ebbe08c 258 // If there is no new record to get exit now.\r
83f6d1a0 259 //\r
2ebbe08c 260 *MonotonicCount = 0;\r
261 return EFI_NOT_FOUND;\r
83f6d1a0 262 }\r
263 }\r
264 }\r
265 //\r
266 // Return the record\r
267 //\r
268 *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);\r
269 if (*Record == NULL) {\r
270 return EFI_NOT_FOUND;\r
271 }\r
272\r
273 if (FilterDriver != NULL) {\r
274 //\r
275 // If we have a filter driver update the records that have been read.\r
276 // If MonotonicCount is zero No more reacords left.\r
277 //\r
278 if (*MonotonicCount == 0) {\r
41e4912f 279 //\r
280 // Save the current Record MonotonicCount.\r
281 //\r
282 FilterDriver->GetNextMonotonicCount = (*Record)->LogMonotonicCount;\r
83f6d1a0 283 } else {\r
284 //\r
285 // Point to next undread record\r
286 //\r
287 FilterDriver->GetNextMonotonicCount = *MonotonicCount;\r
288 }\r
289 }\r
290\r
291 return EFI_SUCCESS;\r
292}\r
293\r
a73d0c74 294/**\r
83f6d1a0 295 This function registers the data hub filter driver that is represented \r
296 by FilterEvent. Only one instance of each FilterEvent can be registered.\r
297 After the FilterEvent is registered, it will be signaled so it can sync \r
298 with data records that have been recorded prior to the FilterEvent being \r
299 registered.\r
300 \r
a73d0c74 301 @param This - The EFI_DATA_HUB_PROTOCOL instance.\r
302 @param FilterEvent - The EFI_EVENT to signal whenever data that matches \r
83f6d1a0 303 FilterClass is logged in the system.\r
a73d0c74 304 @param FilterTpl - The maximum EFI_TPL at which FilterEvent can be \r
83f6d1a0 305 signaled. It is strongly recommended that you use the \r
306 lowest EFI_TPL possible.\r
a73d0c74 307 @param FilterClass - FilterEvent will be signaled whenever a bit in \r
83f6d1a0 308 EFI_DATA_RECORD_HEADER.DataRecordClass is also set in \r
309 FilterClass. If FilterClass is zero, no class-based \r
310 filtering will be performed.\r
a73d0c74 311 @param FilterDataRecordGuid - FilterEvent will be signaled whenever FilterDataRecordGuid \r
83f6d1a0 312 matches EFI_DATA_RECORD_HEADER.DataRecordGuid. If \r
313 FilterDataRecordGuid is NULL, then no GUID-based filtering \r
314 will be performed. \r
83f6d1a0 315\r
a73d0c74 316 @retval EFI_SUCCESS - The filter driver event was registered.\r
317 @retval EFI_ALREADY_STARTED - FilterEvent was previously registered and cannot be \r
83f6d1a0 318 registered again.\r
a73d0c74 319 @retval EFI_OUT_OF_RESOURCES - The filter driver event was not registered due to lack of \r
83f6d1a0 320 system resources.\r
321\r
a73d0c74 322**/\r
a73d0c74 323EFI_STATUS\r
324EFIAPI\r
325DataHubRegisterFilterDriver (\r
326 IN EFI_DATA_HUB_PROTOCOL * This,\r
327 IN EFI_EVENT FilterEvent,\r
328 IN EFI_TPL FilterTpl,\r
329 IN UINT64 FilterClass,\r
330 IN EFI_GUID * FilterDataRecordGuid OPTIONAL\r
331 )\r
332\r
83f6d1a0 333{\r
334 DATA_HUB_INSTANCE *Private;\r
335 DATA_HUB_FILTER_DRIVER *FilterDriver;\r
336\r
337 Private = DATA_HUB_INSTANCE_FROM_THIS (This);\r
338\r
339 FilterDriver = (DATA_HUB_FILTER_DRIVER *) AllocateZeroPool (sizeof (DATA_HUB_FILTER_DRIVER));\r
340 if (FilterDriver == NULL) {\r
341 return EFI_OUT_OF_RESOURCES;\r
342 }\r
343 //\r
344 // Initialize filter driver info\r
345 //\r
346 FilterDriver->Signature = EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE;\r
347 FilterDriver->Event = FilterEvent;\r
348 FilterDriver->Tpl = FilterTpl;\r
349 FilterDriver->GetNextMonotonicCount = 0;\r
350 if (FilterClass == 0) {\r
351 FilterDriver->ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |\r
352 EFI_DATA_RECORD_CLASS_ERROR |\r
353 EFI_DATA_RECORD_CLASS_DATA |\r
354 EFI_DATA_RECORD_CLASS_PROGRESS_CODE;\r
355 } else {\r
356 FilterDriver->ClassFilter = FilterClass;\r
357 }\r
358\r
359 if (FilterDataRecordGuid != NULL) {\r
360 CopyMem (&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID));\r
361 }\r
362 //\r
363 // Search for duplicate entries\r
364 //\r
365 if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) {\r
366 FreePool (FilterDriver);\r
367 return EFI_ALREADY_STARTED;\r
368 }\r
369 //\r
370 // Make insertion an atomic operation with the lock.\r
371 //\r
372 EfiAcquireLock (&Private->DataLock);\r
373 InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link);\r
374 EfiReleaseLock (&Private->DataLock);\r
375\r
376 //\r
377 // Signal the Filter driver we just loaded so they will recieve all the\r
378 // previous history. If we did not signal here we would have to wait until\r
379 // the next data was logged to get the history. In a case where no next\r
380 // data was logged we would never get synced up.\r
381 //\r
382 gBS->SignalEvent (FilterEvent);\r
383\r
384 return EFI_SUCCESS;\r
385}\r
386\r
a73d0c74 387/**\r
83f6d1a0 388 Remove a Filter Driver, so it no longer gets called when data \r
389 information is logged.\r
390\r
a73d0c74 391 @param This - Protocol instance structure\r
83f6d1a0 392\r
a73d0c74 393 @param FilterEvent - Event that represents a filter driver that is to be \r
83f6d1a0 394 Unregistered.\r
395\r
a73d0c74 396 @retval EFI_SUCCESS - If FilterEvent was unregistered\r
83f6d1a0 397\r
a73d0c74 398 @retval EFI_NOT_FOUND - If FilterEvent does not exist\r
83f6d1a0 399\r
a73d0c74 400**/\r
a73d0c74 401EFI_STATUS\r
402EFIAPI\r
403DataHubUnregisterFilterDriver (\r
404 IN EFI_DATA_HUB_PROTOCOL *This,\r
405 IN EFI_EVENT FilterEvent\r
406 )\r
83f6d1a0 407{\r
408 DATA_HUB_INSTANCE *Private;\r
409 DATA_HUB_FILTER_DRIVER *FilterDriver;\r
410\r
411 Private = DATA_HUB_INSTANCE_FROM_THIS (This);\r
412\r
413 //\r
414 // Search for duplicate entries\r
415 //\r
416 FilterDriver = FindFilterDriverByEvent (\r
417 &Private->FilterDriverListHead,\r
418 FilterEvent\r
419 );\r
420 if (FilterDriver == NULL) {\r
421 return EFI_NOT_FOUND;\r
422 }\r
423 //\r
424 // Make removal an atomic operation with the lock\r
425 //\r
426 EfiAcquireLock (&Private->DataLock);\r
427 RemoveEntryList (&FilterDriver->Link);\r
428 EfiReleaseLock (&Private->DataLock);\r
429\r
430 return EFI_SUCCESS;\r
431}\r
83f6d1a0 432\r
a73d0c74 433/**\r
83f6d1a0 434 Search the Head list for a EFI_DATA_HUB_FILTER_DRIVER member that\r
435 represents Event and return it.\r
436\r
a73d0c74 437 @param Head - Head of dual linked list of EFI_DATA_HUB_FILTER_DRIVER\r
83f6d1a0 438 structures.\r
439\r
a73d0c74 440 @param Event - Event to be search for in the Head list.\r
83f6d1a0 441\r
a73d0c74 442 @retval EFI_DATA_HUB_FILTER_DRIVER - Returned if Event stored in the\r
83f6d1a0 443 Head doubly linked list.\r
444\r
a73d0c74 445 @retval NULL - If Event is not in the list\r
446\r
447**/\r
a73d0c74 448DATA_HUB_FILTER_DRIVER *\r
449FindFilterDriverByEvent (\r
450 IN LIST_ENTRY *Head,\r
451 IN EFI_EVENT Event\r
452 )\r
83f6d1a0 453\r
83f6d1a0 454{\r
455 DATA_HUB_FILTER_DRIVER *FilterEntry;\r
456 LIST_ENTRY *Link;\r
457\r
458 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
459 FilterEntry = FILTER_ENTRY_FROM_LINK (Link);\r
460 if (FilterEntry->Event == Event) {\r
461 return FilterEntry;\r
462 }\r
463 }\r
464\r
465 return NULL;\r
466}\r
467\r
a73d0c74 468/**\r
83f6d1a0 469 Search the Head doubly linked list for the passed in MTC. Return the \r
470 matching element in Head and the MTC on the next entry.\r
471\r
a73d0c74 472 @param Head - Head of Data Log linked list.\r
83f6d1a0 473\r
a73d0c74 474 @param ClassFilter - Only match the MTC if it is in the same Class as the\r
83f6d1a0 475 ClassFilter.\r
476\r
a73d0c74 477 @param PtrCurrentMTC - On IN contians MTC to search for. On OUT contians next\r
83f6d1a0 478 MTC in the data log list or zero if at end of the list.\r
479 \r
a73d0c74 480 @retval EFI_DATA_LOG_ENTRY - Return pointer to data log data from Head list.\r
83f6d1a0 481\r
a73d0c74 482 @retval NULL - If no data record exists.\r
83f6d1a0 483\r
a73d0c74 484**/\r
a73d0c74 485EFI_DATA_RECORD_HEADER *\r
486GetNextDataRecord (\r
487 IN LIST_ENTRY *Head,\r
488 IN UINT64 ClassFilter,\r
489 IN OUT UINT64 *PtrCurrentMTC\r
490 )\r
83f6d1a0 491\r
83f6d1a0 492{\r
493 EFI_DATA_ENTRY *LogEntry;\r
494 LIST_ENTRY *Link;\r
495 BOOLEAN ReturnFirstEntry;\r
496 EFI_DATA_RECORD_HEADER *Record;\r
497 EFI_DATA_ENTRY *NextLogEntry;\r
498\r
499 //\r
500 // If MonotonicCount == 0 just return the first one\r
501 //\r
502 ReturnFirstEntry = (BOOLEAN) (*PtrCurrentMTC == 0);\r
503\r
504 Record = NULL;\r
505 for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
506 LogEntry = DATA_ENTRY_FROM_LINK (Link);\r
507 if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) {\r
508 //\r
509 // Skip any entry that does not have the correct ClassFilter\r
510 //\r
511 continue;\r
512 }\r
513\r
514 if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) {\r
515 //\r
516 // Return record to the user\r
517 //\r
518 Record = LogEntry->Record;\r
519\r
520 //\r
521 // Calculate the next MTC value. If there is no next entry set\r
522 // MTC to zero.\r
523 //\r
524 *PtrCurrentMTC = 0;\r
525 for (Link = Link->ForwardLink; Link != Head; Link = Link->ForwardLink) {\r
526 NextLogEntry = DATA_ENTRY_FROM_LINK (Link);\r
527 if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) {\r
528 //\r
529 // Return the MTC of the next thing to search for if found\r
530 //\r
531 *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount;\r
532 break;\r
533 }\r
534 }\r
535 //\r
536 // Record found exit loop and return\r
537 //\r
538 break;\r
539 }\r
540 }\r
541\r
542 return Record;\r
543}\r
83f6d1a0 544\r
a73d0c74 545/**\r
83f6d1a0 546\r
83f6d1a0 547 Install Driver to produce Data Hub protocol. \r
548\r
a73d0c74 549 @param ImageHandle Module's image handle\r
550 @param SystemTable Pointer of EFI_SYSTEM_TABLE\r
83f6d1a0 551\r
83f6d1a0 552\r
a73d0c74 553 @retval EFI_SUCCESS - Logging Hub protocol installed\r
83f6d1a0 554\r
a73d0c74 555 @retval Other - No protocol installed, unload driver.\r
83f6d1a0 556\r
a73d0c74 557**/\r
558EFI_STATUS\r
559EFIAPI\r
560DataHubInstall (\r
561 IN EFI_HANDLE ImageHandle,\r
562 IN EFI_SYSTEM_TABLE *SystemTable\r
563 )\r
83f6d1a0 564{\r
565 EFI_STATUS Status;\r
566 UINT32 HighMontonicCount;\r
567\r
568 mPrivateData.Signature = DATA_HUB_INSTANCE_SIGNATURE;\r
569 mPrivateData.DataHub.LogData = DataHubLogData;\r
570 mPrivateData.DataHub.GetNextRecord = DataHubGetNextRecord;\r
571 mPrivateData.DataHub.RegisterFilterDriver = DataHubRegisterFilterDriver;\r
572 mPrivateData.DataHub.UnregisterFilterDriver = DataHubUnregisterFilterDriver;\r
573\r
574 //\r
575 // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is\r
576 // required by this protocol\r
577 //\r
578 InitializeListHead (&mPrivateData.DataListHead);\r
579 InitializeListHead (&mPrivateData.FilterDriverListHead);\r
580\r
581 EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);\r
582\r
583 //\r
584 // Make sure we get a bigger MTC number on every boot!\r
585 //\r
586 Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount);\r
587 if (EFI_ERROR (Status)) {\r
588 //\r
589 // if system service fails pick a sane value.\r
590 //\r
591 mPrivateData.GlobalMonotonicCount = 0;\r
592 } else {\r
593 mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64) HighMontonicCount, 32);\r
594 }\r
595 //\r
596 // Make a new handle and install the protocol\r
597 //\r
598 mPrivateData.Handle = NULL;\r
599 Status = gBS->InstallProtocolInterface (\r
600 &mPrivateData.Handle,\r
601 &gEfiDataHubProtocolGuid,\r
602 EFI_NATIVE_INTERFACE,\r
603 &mPrivateData.DataHub\r
604 );\r
605 return Status;\r
606}\r
a73d0c74 607\r