OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
DataHub.c
Go to the documentation of this file.
1
10#include "DataHub.h"
11
12//
13// Since this driver will only ever produce one instance of the Logging Hub
14// protocol you are not required to dynamically allocate the PrivateData.
15//
17
32EFI_STATUS
33EFIAPI
35 IN EFI_DATA_HUB_PROTOCOL *This,
36 IN EFI_GUID *DataRecordGuid,
37 IN EFI_GUID *ProducerName,
38 IN UINT64 DataRecordClass,
39 IN VOID *RawData,
40 IN UINT32 RawDataSize
41 )
42{
43 EFI_STATUS Status;
44 DATA_HUB_INSTANCE *Private;
45 EFI_DATA_ENTRY *LogEntry;
46 UINT32 TotalSize;
47 UINT32 RecordSize;
49 VOID *Raw;
50 DATA_HUB_FILTER_DRIVER *FilterEntry;
51 LIST_ENTRY *Link;
52 LIST_ENTRY *Head;
53 EFI_TIME LogTime;
54
55 Private = DATA_HUB_INSTANCE_FROM_THIS (This);
56
57 //
58 // Combine the storage for the internal structs and a copy of the log record.
59 // Record follows PrivateLogEntry. The consumer will be returned a pointer
60 // to Record so we don't what it to be the thing that was allocated from
61 // pool, so the consumer can't free an data record by mistake.
62 //
63 RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize;
64 TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize;
65
66 //
67 // First try to get log time at TPL level <= TPL_CALLBACK.
68 //
69 ZeroMem (&LogTime, sizeof (LogTime));
70 if (EfiGetCurrentTpl () <= TPL_CALLBACK) {
71 gRT->GetTime (&LogTime, NULL);
72 }
73
74 //
75 // The Logging action is the critical section, so it is locked.
76 // The MTC asignment & update and logging must be an
77 // atomic operation, so use the lock.
78 //
79 Status = EfiAcquireLockOrFail (&Private->DataLock);
80 if (EFI_ERROR (Status)) {
81 //
82 // Reentrancy detected so exit!
83 //
84 return Status;
85 }
86
87 LogEntry = AllocatePool (TotalSize);
88
89 if (LogEntry == NULL) {
90 EfiReleaseLock (&Private->DataLock);
91 return EFI_OUT_OF_RESOURCES;
92 }
93
94 ZeroMem (LogEntry, TotalSize);
95
96 Record = (EFI_DATA_RECORD_HEADER *)(LogEntry + 1);
97 Raw = (VOID *)(Record + 1);
98
99 //
100 // Build Standard Log Header
101 //
103 Record->HeaderSize = (UINT16)sizeof (EFI_DATA_RECORD_HEADER);
104 Record->RecordSize = RecordSize;
105 CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID));
106 CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID));
107 Record->DataRecordClass = DataRecordClass;
108
109 //
110 // Ensure LogMonotonicCount is not zero
111 //
112 Record->LogMonotonicCount = ++Private->GlobalMonotonicCount;
113
114 CopyMem (&Record->LogTime, &LogTime, sizeof (LogTime));
115
116 //
117 // Insert log into the internal linked list.
118 //
120 LogEntry->Record = Record;
121 LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize;
122 InsertTailList (&Private->DataListHead, &LogEntry->Link);
123
124 CopyMem (Raw, RawData, RawDataSize);
125
126 EfiReleaseLock (&Private->DataLock);
127
128 //
129 // Send Signal to all the filter drivers which are interested
130 // in the record's class and guid.
131 //
132 Head = &Private->FilterDriverListHead;
133 for (Link = GetFirstNode (Head); Link != Head; Link = GetNextNode (Head, Link)) {
134 FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
135 if (((FilterEntry->ClassFilter & DataRecordClass) != 0) &&
136 (IsZeroGuid (&FilterEntry->FilterDataRecordGuid) ||
137 CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid)))
138 {
139 gBS->SignalEvent (FilterEntry->Event);
140 }
141 }
142
143 return EFI_SUCCESS;
144}
145
162 IN LIST_ENTRY *Head,
163 IN UINT64 ClassFilter,
164 IN OUT UINT64 *PtrCurrentMTC
165 )
166
167{
168 EFI_DATA_ENTRY *LogEntry;
169 LIST_ENTRY *Link;
170 BOOLEAN ReturnFirstEntry;
172 EFI_DATA_ENTRY *NextLogEntry;
173
174 //
175 // If MonotonicCount == 0 just return the first one
176 //
177 ReturnFirstEntry = (BOOLEAN)(*PtrCurrentMTC == 0);
178
179 Record = NULL;
180 for (Link = GetFirstNode (Head); Link != Head; Link = GetNextNode (Head, Link)) {
181 LogEntry = DATA_ENTRY_FROM_LINK (Link);
182 if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) {
183 //
184 // Skip any entry that does not have the correct ClassFilter
185 //
186 continue;
187 }
188
189 if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) {
190 //
191 // Return record to the user
192 //
193 Record = LogEntry->Record;
194
195 //
196 // Calculate the next MTC value. If there is no next entry set
197 // MTC to zero.
198 //
199 *PtrCurrentMTC = 0;
200 for (Link = GetNextNode (Head, Link); Link != Head; Link = GetNextNode (Head, Link)) {
201 NextLogEntry = DATA_ENTRY_FROM_LINK (Link);
202 if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) {
203 //
204 // Return the MTC of the next thing to search for if found
205 //
206 *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount;
207 break;
208 }
209 }
210
211 //
212 // Record found exit loop and return
213 //
214 break;
215 }
216 }
217
218 return Record;
219}
220
234 IN LIST_ENTRY *Head,
235 IN EFI_EVENT Event
236 )
237{
238 DATA_HUB_FILTER_DRIVER *FilterEntry;
239 LIST_ENTRY *Link;
240
241 for (Link = GetFirstNode (Head); Link != Head; Link = GetNextNode (Head, Link)) {
242 FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
243 if (FilterEntry->Event == Event) {
244 return FilterEntry;
245 }
246 }
247
248 return NULL;
249}
250
280EFI_STATUS
281EFIAPI
283 IN EFI_DATA_HUB_PROTOCOL *This,
284 IN OUT UINT64 *MonotonicCount,
285 IN EFI_EVENT *FilterDriverEvent, OPTIONAL
286 OUT EFI_DATA_RECORD_HEADER **Record
287 )
288{
289 DATA_HUB_INSTANCE *Private;
290 DATA_HUB_FILTER_DRIVER *FilterDriver;
291 UINT64 ClassFilter;
292
293 Private = DATA_HUB_INSTANCE_FROM_THIS (This);
294
295 FilterDriver = NULL;
296 ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |
300
301 //
302 // If FilterDriverEvent is NULL, then return the next record
303 //
304 if (FilterDriverEvent == NULL) {
305 *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
306 if (*Record == NULL) {
307 return EFI_NOT_FOUND;
308 }
309
310 return EFI_SUCCESS;
311 }
312
313 //
314 // For events the beginning is the last unread record. This info is
315 // stored in the instance structure, so we must look up the event
316 // to get the data.
317 //
318 FilterDriver = FindFilterDriverByEvent (
319 &Private->FilterDriverListHead,
320 *FilterDriverEvent
321 );
322 if (FilterDriver == NULL) {
323 return EFI_INVALID_PARAMETER;
324 }
325
326 //
327 // Use the Class filter the event was created with.
328 //
329 ClassFilter = FilterDriver->ClassFilter;
330
331 //
332 // Retrieve the next record or the first record.
333 //
334 if ((*MonotonicCount != 0) || (FilterDriver->GetNextMonotonicCount == 0)) {
335 *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
336 if (*Record == NULL) {
337 return EFI_NOT_FOUND;
338 }
339
340 if (*MonotonicCount != 0) {
341 //
342 // If this was not the last record then update the count associated with the filter
343 //
344 FilterDriver->GetNextMonotonicCount = *MonotonicCount;
345 } else {
346 //
347 // Save the MonotonicCount of the last record which has been read
348 //
349 FilterDriver->GetNextMonotonicCount = (*Record)->LogMonotonicCount;
350 }
351
352 return EFI_SUCCESS;
353 }
354
355 //
356 // This is a request to read the first record that has not been read yet.
357 // Set MonotoicCount to the last record successfuly read
358 //
359 *MonotonicCount = FilterDriver->GetNextMonotonicCount;
360
361 //
362 // Retrieve the last record successfuly read again, but do not return it since
363 // it has already been returned before.
364 //
365 *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
366 if (*Record == NULL) {
367 return EFI_NOT_FOUND;
368 }
369
370 if (*MonotonicCount != 0) {
371 //
372 // Update the count associated with the filter
373 //
374 FilterDriver->GetNextMonotonicCount = *MonotonicCount;
375
376 //
377 // Retrieve the record after the last record successfuly read
378 //
379 *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
380 if (*Record == NULL) {
381 return EFI_NOT_FOUND;
382 }
383 }
384
385 return EFI_SUCCESS;
386}
387
417EFI_STATUS
418EFIAPI
420 IN EFI_DATA_HUB_PROTOCOL *This,
421 IN EFI_EVENT FilterEvent,
422 IN EFI_TPL FilterTpl,
423 IN UINT64 FilterClass,
424 IN EFI_GUID *FilterDataRecordGuid OPTIONAL
425 )
426
427{
428 DATA_HUB_INSTANCE *Private;
429 DATA_HUB_FILTER_DRIVER *FilterDriver;
430
431 Private = DATA_HUB_INSTANCE_FROM_THIS (This);
432
433 FilterDriver = (DATA_HUB_FILTER_DRIVER *)AllocateZeroPool (sizeof (DATA_HUB_FILTER_DRIVER));
434 if (FilterDriver == NULL) {
435 return EFI_OUT_OF_RESOURCES;
436 }
437
438 //
439 // Initialize filter driver info
440 //
442 FilterDriver->Event = FilterEvent;
443 FilterDriver->Tpl = FilterTpl;
444 FilterDriver->GetNextMonotonicCount = 0;
445 if (FilterClass == 0) {
450 } else {
451 FilterDriver->ClassFilter = FilterClass;
452 }
453
454 if (FilterDataRecordGuid != NULL) {
455 CopyMem (&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID));
456 }
457
458 //
459 // Search for duplicate entries
460 //
461 if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) {
462 FreePool (FilterDriver);
463 return EFI_ALREADY_STARTED;
464 }
465
466 //
467 // Make insertion an atomic operation with the lock.
468 //
469 EfiAcquireLock (&Private->DataLock);
470 InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link);
471 EfiReleaseLock (&Private->DataLock);
472
473 //
474 // Signal the Filter driver we just loaded so they will recieve all the
475 // previous history. If we did not signal here we would have to wait until
476 // the next data was logged to get the history. In a case where no next
477 // data was logged we would never get synced up.
478 //
479 gBS->SignalEvent (FilterEvent);
480
481 return EFI_SUCCESS;
482}
483
496EFI_STATUS
497EFIAPI
499 IN EFI_DATA_HUB_PROTOCOL *This,
500 IN EFI_EVENT FilterEvent
501 )
502{
503 DATA_HUB_INSTANCE *Private;
504 DATA_HUB_FILTER_DRIVER *FilterDriver;
505
506 Private = DATA_HUB_INSTANCE_FROM_THIS (This);
507
508 //
509 // Search for duplicate entries
510 //
511 FilterDriver = FindFilterDriverByEvent (
512 &Private->FilterDriverListHead,
513 FilterEvent
514 );
515 if (FilterDriver == NULL) {
516 return EFI_NOT_FOUND;
517 }
518
519 //
520 // Make removal an atomic operation with the lock
521 //
522 EfiAcquireLock (&Private->DataLock);
523 RemoveEntryList (&FilterDriver->Link);
524 EfiReleaseLock (&Private->DataLock);
525
526 return EFI_SUCCESS;
527}
528
529//
530// CHANGE: Function prototype has been adapted to fit the other OC APIs.
531//
532
539 VOID
540 )
541{
542 EFI_STATUS Status;
543 UINT32 HighMontonicCount;
544
550
551 //
552 // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is
553 // required by this protocol
554 //
555 InitializeListHead (&mPrivateData.DataListHead);
556 InitializeListHead (&mPrivateData.FilterDriverListHead);
557
558 EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
559
560 //
561 // Make sure we get a bigger MTC number on every boot!
562 //
563 Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount);
564 if (EFI_ERROR (Status)) {
565 //
566 // if system service fails pick a sane value.
567 //
569 } else {
570 mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64)HighMontonicCount, 32);
571 }
572
573 //
574 // Make a new handle and install the protocol
575 //
576 mPrivateData.Handle = NULL;
577 Status = gBS->InstallProtocolInterface (
580 EFI_NATIVE_INTERFACE,
582 );
583 //
584 // CHANGE: Return the interface instead of the install status.
585 //
586 if (EFI_ERROR (Status)) {
587 return NULL;
588 }
589
590 return &mPrivateData.DataHub;
591}
EFI_STATUS EFIAPI DataHubLogData(IN EFI_DATA_HUB_PROTOCOL *This, IN EFI_GUID *DataRecordGuid, IN EFI_GUID *ProducerName, IN UINT64 DataRecordClass, IN VOID *RawData, IN UINT32 RawDataSize)
Definition DataHub.c:34
EFI_DATA_RECORD_HEADER * GetNextDataRecord(IN LIST_ENTRY *Head, IN UINT64 ClassFilter, IN OUT UINT64 *PtrCurrentMTC)
Definition DataHub.c:161
EFI_STATUS EFIAPI DataHubUnregisterFilterDriver(IN EFI_DATA_HUB_PROTOCOL *This, IN EFI_EVENT FilterEvent)
Definition DataHub.c:498
DATA_HUB_INSTANCE mPrivateData
Definition DataHub.c:16
EFI_DATA_HUB_PROTOCOL * DataHubInstall(VOID)
Definition DataHub.c:538
EFI_STATUS EFIAPI DataHubRegisterFilterDriver(IN EFI_DATA_HUB_PROTOCOL *This, IN EFI_EVENT FilterEvent, IN EFI_TPL FilterTpl, IN UINT64 FilterClass, IN EFI_GUID *FilterDataRecordGuid OPTIONAL)
Definition DataHub.c:419
DATA_HUB_FILTER_DRIVER * FindFilterDriverByEvent(IN LIST_ENTRY *Head, IN EFI_EVENT Event)
Definition DataHub.c:233
EFI_STATUS EFIAPI DataHubGetNextRecord(IN EFI_DATA_HUB_PROTOCOL *This, IN OUT UINT64 *MonotonicCount, IN EFI_EVENT *FilterDriverEvent, OPTIONAL OUT EFI_DATA_RECORD_HEADER **Record)
Definition DataHub.c:282
#define EFI_DATA_RECORD_CLASS_DATA
Definition DataHub.h:64
#define EFI_DATA_RECORD_CLASS_DEBUG
Definition DataHub.h:62
#define EFI_DATA_RECORD_CLASS_PROGRESS_CODE
Definition DataHub.h:65
#define EFI_DATA_RECORD_CLASS_ERROR
Definition DataHub.h:63
#define EFI_DATA_RECORD_HEADER_VERSION
Definition DataHub.h:44
EFI_GUID gEfiDataHubProtocolGuid
#define DATA_HUB_INSTANCE_SIGNATURE
Definition DataHub.h:26
#define FILTER_ENTRY_FROM_LINK(link)
Definition DataHub.h:117
#define DATA_ENTRY_FROM_LINK(link)
Definition DataHub.h:82
#define DATA_HUB_INSTANCE_FROM_THIS(this)
Definition DataHub.h:65
#define EFI_DATA_ENTRY_SIGNATURE
Definition DataHub.h:72
#define EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE
Definition DataHub.h:88
EFI_BOOT_SERVICES * gBS
UINTN Head
Definition OcTypingLib.h:46
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
BOOLEAN EFIAPI IsZeroGuid(IN CONST GUID *Guid)
EFI_RUNTIME_SERVICES * gRT
UINT64 EFIAPI LShiftU64(IN UINT64 Operand, IN UINTN Count)
Definition UserMath.c:76
EFI_DATA_HUB_UNREGISTER_FILTER_DRIVER UnregisterFilterDriver
Definition DataHub.h:217
EFI_DATA_HUB_GET_NEXT_RECORD GetNextRecord
Definition DataHub.h:207
EFI_DATA_HUB_LOG_DATA LogData
Definition DataHub.h:201
EFI_DATA_HUB_REGISTER_FILTER_DRIVER RegisterFilterDriver
Definition DataHub.h:212
EFI_GUID FilterDataRecordGuid
Definition DataHub.h:114
UINT64 GetNextMonotonicCount
Definition DataHub.h:104
EFI_DATA_HUB_PROTOCOL DataHub
Definition DataHub.h:35
EFI_HANDLE Handle
Definition DataHub.h:30
UINT64 GlobalMonotonicCount
Definition DataHub.h:50
LIST_ENTRY FilterDriverListHead
Definition DataHub.h:62
LIST_ENTRY DataListHead
Definition DataHub.h:56
EFI_LOCK DataLock
Definition DataHub.h:44
UINT32 Signature
Definition DataHub.h:28
UINTN RecordSize
Definition DataHub.h:79
EFI_DATA_RECORD_HEADER * Record
Definition DataHub.h:77
LIST_ENTRY Link
Definition DataHub.h:75
UINT32 Signature
Definition DataHub.h:74
EFI_GUID ProducerName
Definition DataHub.h:50
EFI_GUID DataRecordGuid
Definition DataHub.h:49