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