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