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