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