12ab239290ded075c540a463815dae5e74fea52c6klu/** @file
283f6d1a03b9037663fb1587d135020c7333235cbqhuang  This code produces the Data Hub protocol. It preloads the data hub
383f6d1a03b9037663fb1587d135020c7333235cbqhuang  with status information copied in from PEI HOBs.
483f6d1a03b9037663fb1587d135020c7333235cbqhuang
56692e0a89e3f4e6ffb101060e811990ac2815be5Hao WuCopyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
6180a5a35cb49699bd249dee19e41cee34c856a58hhtianThis program and the accompanying materials
73db510989eb500296c3f4839c427325a02aea2e3kluare licensed and made available under the terms and conditions of the BSD License
83db510989eb500296c3f4839c427325a02aea2e3kluwhich accompanies this distribution.  The full text of the license may be found at
93db510989eb500296c3f4839c427325a02aea2e3kluhttp://opensource.org/licenses/bsd-license.php
103db510989eb500296c3f4839c427325a02aea2e3klu
113db510989eb500296c3f4839c427325a02aea2e3kluTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
123db510989eb500296c3f4839c427325a02aea2e3kluWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
133db510989eb500296c3f4839c427325a02aea2e3klu
143db510989eb500296c3f4839c427325a02aea2e3klu**/
1583f6d1a03b9037663fb1587d135020c7333235cbqhuang
1683f6d1a03b9037663fb1587d135020c7333235cbqhuang#include "DataHub.h"
1783f6d1a03b9037663fb1587d135020c7333235cbqhuang
1883f6d1a03b9037663fb1587d135020c7333235cbqhuang//
199f6531d14d145918079d03926ff827f6c1a274a4gikidy//  Since this driver will only ever produce one instance of the Logging Hub
209f6531d14d145918079d03926ff827f6c1a274a4gikidy//  protocol you are not required to dynamically allocate the PrivateData.
219f6531d14d145918079d03926ff827f6c1a274a4gikidy//
229f6531d14d145918079d03926ff827f6c1a274a4gikidyDATA_HUB_INSTANCE mPrivateData;
239f6531d14d145918079d03926ff827f6c1a274a4gikidy
24a73d0c743b5192b1038a24711525eed71dfa300fklu/**
25a73d0c743b5192b1038a24711525eed71dfa300fklu  Log data record into the data logging hub
26a73d0c743b5192b1038a24711525eed71dfa300fklu
272ab239290ded075c540a463815dae5e74fea52c6klu  @param This                   Protocol instance structure
282ab239290ded075c540a463815dae5e74fea52c6klu  @param DataRecordGuid         GUID that defines record contents
292ab239290ded075c540a463815dae5e74fea52c6klu  @param ProducerName           GUID that defines the name of the producer of the data
302ab239290ded075c540a463815dae5e74fea52c6klu  @param DataRecordClass        Class that defines generic record type
312ab239290ded075c540a463815dae5e74fea52c6klu  @param RawData                Data Log record as defined by DataRecordGuid
322ab239290ded075c540a463815dae5e74fea52c6klu  @param RawDataSize            Size of Data Log data in bytes
33a73d0c743b5192b1038a24711525eed71dfa300fklu
342ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_SUCCESS           If data was logged
352ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_OUT_OF_RESOURCES  If data was not logged due to lack of system
362ab239290ded075c540a463815dae5e74fea52c6klu                                resources.
37a73d0c743b5192b1038a24711525eed71dfa300fklu**/
3883f6d1a03b9037663fb1587d135020c7333235cbqhuangEFI_STATUS
3983f6d1a03b9037663fb1587d135020c7333235cbqhuangEFIAPI
4083f6d1a03b9037663fb1587d135020c7333235cbqhuangDataHubLogData (
4183f6d1a03b9037663fb1587d135020c7333235cbqhuang  IN  EFI_DATA_HUB_PROTOCOL   *This,
4283f6d1a03b9037663fb1587d135020c7333235cbqhuang  IN  EFI_GUID                *DataRecordGuid,
4383f6d1a03b9037663fb1587d135020c7333235cbqhuang  IN  EFI_GUID                *ProducerName,
4483f6d1a03b9037663fb1587d135020c7333235cbqhuang  IN  UINT64                  DataRecordClass,
4583f6d1a03b9037663fb1587d135020c7333235cbqhuang  IN  VOID                    *RawData,
4683f6d1a03b9037663fb1587d135020c7333235cbqhuang  IN  UINT32                  RawDataSize
4783f6d1a03b9037663fb1587d135020c7333235cbqhuang  )
4883f6d1a03b9037663fb1587d135020c7333235cbqhuang{
4983f6d1a03b9037663fb1587d135020c7333235cbqhuang  EFI_STATUS              Status;
5083f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_INSTANCE       *Private;
5183f6d1a03b9037663fb1587d135020c7333235cbqhuang  EFI_DATA_ENTRY          *LogEntry;
5283f6d1a03b9037663fb1587d135020c7333235cbqhuang  UINT32                  TotalSize;
5383f6d1a03b9037663fb1587d135020c7333235cbqhuang  UINT32                  RecordSize;
5483f6d1a03b9037663fb1587d135020c7333235cbqhuang  EFI_DATA_RECORD_HEADER  *Record;
5583f6d1a03b9037663fb1587d135020c7333235cbqhuang  VOID                    *Raw;
5683f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_FILTER_DRIVER  *FilterEntry;
5783f6d1a03b9037663fb1587d135020c7333235cbqhuang  LIST_ENTRY              *Link;
5883f6d1a03b9037663fb1587d135020c7333235cbqhuang  LIST_ENTRY              *Head;
59b4c900588691090ae931a630b93f5c8753677e68lgao  EFI_TIME                LogTime;
6083f6d1a03b9037663fb1587d135020c7333235cbqhuang
6183f6d1a03b9037663fb1587d135020c7333235cbqhuang  Private = DATA_HUB_INSTANCE_FROM_THIS (This);
6283f6d1a03b9037663fb1587d135020c7333235cbqhuang
6383f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
6483f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Combine the storage for the internal structs and a copy of the log record.
6583f6d1a03b9037663fb1587d135020c7333235cbqhuang  //  Record follows PrivateLogEntry. The consumer will be returned a pointer
6683f6d1a03b9037663fb1587d135020c7333235cbqhuang  //  to Record so we don't what it to be the thing that was allocated from
6783f6d1a03b9037663fb1587d135020c7333235cbqhuang  //  pool, so the consumer can't free an data record by mistake.
6883f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
6983f6d1a03b9037663fb1587d135020c7333235cbqhuang  RecordSize  = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize;
7083f6d1a03b9037663fb1587d135020c7333235cbqhuang  TotalSize   = sizeof (EFI_DATA_ENTRY) + RecordSize;
71b4c900588691090ae931a630b93f5c8753677e68lgao
72b4c900588691090ae931a630b93f5c8753677e68lgao  //
73b4c900588691090ae931a630b93f5c8753677e68lgao  // First try to get log time at TPL level <= TPL_CALLBACK.
74b4c900588691090ae931a630b93f5c8753677e68lgao  //
75b4c900588691090ae931a630b93f5c8753677e68lgao  ZeroMem (&LogTime, sizeof (LogTime));
76b4c900588691090ae931a630b93f5c8753677e68lgao  if (EfiGetCurrentTpl() <= TPL_CALLBACK) {
77b4c900588691090ae931a630b93f5c8753677e68lgao    gRT->GetTime (&LogTime, NULL);
78b4c900588691090ae931a630b93f5c8753677e68lgao  }
7983f6d1a03b9037663fb1587d135020c7333235cbqhuang
8083f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
8183f6d1a03b9037663fb1587d135020c7333235cbqhuang  // The Logging action is the critical section, so it is locked.
82b4c900588691090ae931a630b93f5c8753677e68lgao  //  The MTC asignment & update and logging must be an
8383f6d1a03b9037663fb1587d135020c7333235cbqhuang  //  atomic operation, so use the lock.
8483f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
8583f6d1a03b9037663fb1587d135020c7333235cbqhuang  Status = EfiAcquireLockOrFail (&Private->DataLock);
8683f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (EFI_ERROR (Status)) {
8783f6d1a03b9037663fb1587d135020c7333235cbqhuang    //
8883f6d1a03b9037663fb1587d135020c7333235cbqhuang    // Reentrancy detected so exit!
8983f6d1a03b9037663fb1587d135020c7333235cbqhuang    //
9083f6d1a03b9037663fb1587d135020c7333235cbqhuang    return Status;
9183f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
9283f6d1a03b9037663fb1587d135020c7333235cbqhuang
9383f6d1a03b9037663fb1587d135020c7333235cbqhuang  LogEntry = AllocatePool (TotalSize);
9483f6d1a03b9037663fb1587d135020c7333235cbqhuang
9583f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (LogEntry == NULL) {
9683f6d1a03b9037663fb1587d135020c7333235cbqhuang    EfiReleaseLock (&Private->DataLock);
9783f6d1a03b9037663fb1587d135020c7333235cbqhuang    return EFI_OUT_OF_RESOURCES;
9883f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
9983f6d1a03b9037663fb1587d135020c7333235cbqhuang
10083f6d1a03b9037663fb1587d135020c7333235cbqhuang  ZeroMem (LogEntry, TotalSize);
10183f6d1a03b9037663fb1587d135020c7333235cbqhuang
10283f6d1a03b9037663fb1587d135020c7333235cbqhuang  Record  = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1);
10383f6d1a03b9037663fb1587d135020c7333235cbqhuang  Raw     = (VOID *) (Record + 1);
10483f6d1a03b9037663fb1587d135020c7333235cbqhuang
10583f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
10683f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Build Standard Log Header
10783f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
10883f6d1a03b9037663fb1587d135020c7333235cbqhuang  Record->Version     = EFI_DATA_RECORD_HEADER_VERSION;
10913314ba32a0b7eadda3c2340090b66bc0b99cd26xli  Record->HeaderSize  = (UINT16) sizeof (EFI_DATA_RECORD_HEADER);
11083f6d1a03b9037663fb1587d135020c7333235cbqhuang  Record->RecordSize  = RecordSize;
11183f6d1a03b9037663fb1587d135020c7333235cbqhuang  CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID));
11283f6d1a03b9037663fb1587d135020c7333235cbqhuang  CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID));
11383f6d1a03b9037663fb1587d135020c7333235cbqhuang  Record->DataRecordClass   = DataRecordClass;
11483f6d1a03b9037663fb1587d135020c7333235cbqhuang
11541e4912f2932985647927229118179d1f5eb0283eric_tian  //
11641e4912f2932985647927229118179d1f5eb0283eric_tian  // Ensure LogMonotonicCount is not zero
11741e4912f2932985647927229118179d1f5eb0283eric_tian  //
11841e4912f2932985647927229118179d1f5eb0283eric_tian  Record->LogMonotonicCount = ++Private->GlobalMonotonicCount;
11983f6d1a03b9037663fb1587d135020c7333235cbqhuang
120b4c900588691090ae931a630b93f5c8753677e68lgao  CopyMem (&Record->LogTime, &LogTime, sizeof (LogTime));
12183f6d1a03b9037663fb1587d135020c7333235cbqhuang
12283f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
12383f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Insert log into the internal linked list.
12483f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
12583f6d1a03b9037663fb1587d135020c7333235cbqhuang  LogEntry->Signature   = EFI_DATA_ENTRY_SIGNATURE;
12683f6d1a03b9037663fb1587d135020c7333235cbqhuang  LogEntry->Record      = Record;
12783f6d1a03b9037663fb1587d135020c7333235cbqhuang  LogEntry->RecordSize  = sizeof (EFI_DATA_ENTRY) + RawDataSize;
12883f6d1a03b9037663fb1587d135020c7333235cbqhuang  InsertTailList (&Private->DataListHead, &LogEntry->Link);
12983f6d1a03b9037663fb1587d135020c7333235cbqhuang
13083f6d1a03b9037663fb1587d135020c7333235cbqhuang  CopyMem (Raw, RawData, RawDataSize);
13183f6d1a03b9037663fb1587d135020c7333235cbqhuang
13283f6d1a03b9037663fb1587d135020c7333235cbqhuang  EfiReleaseLock (&Private->DataLock);
13383f6d1a03b9037663fb1587d135020c7333235cbqhuang
13483f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
13583f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Send Signal to all the filter drivers which are interested
13683f6d1a03b9037663fb1587d135020c7333235cbqhuang  //  in the record's class and guid.
13783f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
13883f6d1a03b9037663fb1587d135020c7333235cbqhuang  Head = &Private->FilterDriverListHead;
1392ab239290ded075c540a463815dae5e74fea52c6klu  for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
14083f6d1a03b9037663fb1587d135020c7333235cbqhuang    FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
14183f6d1a03b9037663fb1587d135020c7333235cbqhuang    if (((FilterEntry->ClassFilter & DataRecordClass) != 0) &&
14283f6d1a03b9037663fb1587d135020c7333235cbqhuang        (CompareGuid (&FilterEntry->FilterDataRecordGuid, &gZeroGuid) ||
14383f6d1a03b9037663fb1587d135020c7333235cbqhuang         CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) {
14483f6d1a03b9037663fb1587d135020c7333235cbqhuang      gBS->SignalEvent (FilterEntry->Event);
14583f6d1a03b9037663fb1587d135020c7333235cbqhuang    }
14683f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
14783f6d1a03b9037663fb1587d135020c7333235cbqhuang
14883f6d1a03b9037663fb1587d135020c7333235cbqhuang  return EFI_SUCCESS;
14983f6d1a03b9037663fb1587d135020c7333235cbqhuang}
15083f6d1a03b9037663fb1587d135020c7333235cbqhuang
151a73d0c743b5192b1038a24711525eed71dfa300fklu/**
1528b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  Search the Head doubly linked list for the passed in MTC. Return the
1538b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  matching element in Head and the MTC on the next entry.
1548b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
1558b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @param Head             Head of Data Log linked list.
1568b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @param ClassFilter      Only match the MTC if it is in the same Class as the
1578b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu                          ClassFilter.
1588b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @param PtrCurrentMTC    On IN contians MTC to search for. On OUT contians next
1598b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu                          MTC in the data log list or zero if at end of the list.
1608b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
1618b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @retval EFI_DATA_LOG_ENTRY  Return pointer to data log data from Head list.
1628b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @retval NULL                If no data record exists.
1638b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
1648b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu**/
1658b7a3578165b14ebbadc08e80fdfdf88fd2afde4kluEFI_DATA_RECORD_HEADER *
1668b7a3578165b14ebbadc08e80fdfdf88fd2afde4kluGetNextDataRecord (
1678b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  IN  LIST_ENTRY          *Head,
1688b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  IN  UINT64              ClassFilter,
1698b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  IN OUT  UINT64          *PtrCurrentMTC
1708b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  )
1718b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
1728b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu{
1738b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  EFI_DATA_ENTRY          *LogEntry;
1748b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  LIST_ENTRY              *Link;
1758b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  BOOLEAN                 ReturnFirstEntry;
1768b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  EFI_DATA_RECORD_HEADER  *Record;
1778b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  EFI_DATA_ENTRY          *NextLogEntry;
1788b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
1798b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  //
1808b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  // If MonotonicCount == 0 just return the first one
1818b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  //
1828b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  ReturnFirstEntry  = (BOOLEAN) (*PtrCurrentMTC == 0);
1838b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
1848b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  Record            = NULL;
1858b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
1868b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    LogEntry = DATA_ENTRY_FROM_LINK (Link);
1878b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) {
1888b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
1898b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      // Skip any entry that does not have the correct ClassFilter
1908b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
1918b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      continue;
1928b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    }
1938b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
1948b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) {
1958b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
1968b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      // Return record to the user
1978b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
1988b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      Record = LogEntry->Record;
1998b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2008b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
2018b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      // Calculate the next MTC value. If there is no next entry set
2028b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      // MTC to zero.
2038b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
2048b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      *PtrCurrentMTC = 0;
2058b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      for (Link = GetNextNode(Head, Link); Link != Head; Link = GetNextNode(Head, Link)) {
2068b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu        NextLogEntry = DATA_ENTRY_FROM_LINK (Link);
2078b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu        if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) {
2088b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu          //
2098b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu          // Return the MTC of the next thing to search for if found
2108b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu          //
2118b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu          *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount;
2128b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu          break;
2138b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu        }
2148b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      }
2158b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
2168b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      // Record found exit loop and return
2178b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      //
2188b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      break;
2198b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    }
2208b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  }
2218b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2228b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  return Record;
2238b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu}
2248b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2258b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu/**
2268b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  Search the Head list for a EFI_DATA_HUB_FILTER_DRIVER member that
2278b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  represents Event and return it.
2288b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2298b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @param Head   Pointer to head of dual linked list of EFI_DATA_HUB_FILTER_DRIVER structures.
2308b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @param Event  Event to be search for in the Head list.
2318b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2328b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @retval EFI_DATA_HUB_FILTER_DRIVER  Returned if Event stored in the Head doubly linked list.
2338b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  @retval NULL                        If Event is not in the list
2348b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2358b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu**/
2368b7a3578165b14ebbadc08e80fdfdf88fd2afde4kluDATA_HUB_FILTER_DRIVER *
2378b7a3578165b14ebbadc08e80fdfdf88fd2afde4kluFindFilterDriverByEvent (
2388b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  IN  LIST_ENTRY      *Head,
2398b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  IN  EFI_EVENT       Event
2408b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  )
2418b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu{
2428b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  DATA_HUB_FILTER_DRIVER  *FilterEntry;
2438b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  LIST_ENTRY              *Link;
2448b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2458b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  for (Link = GetFirstNode(Head); Link != Head; Link = GetNextNode(Head, Link)) {
2468b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    FilterEntry = FILTER_ENTRY_FROM_LINK (Link);
2478b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    if (FilterEntry->Event == Event) {
2488b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu      return FilterEntry;
2498b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu    }
2508b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  }
2518b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2528b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu  return NULL;
2538b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu}
2548b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu
2558b7a3578165b14ebbadc08e80fdfdf88fd2afde4klu/**
25683f6d1a03b9037663fb1587d135020c7333235cbqhuang
25783f6d1a03b9037663fb1587d135020c7333235cbqhuang  Get a previously logged data record and the MonotonicCount for the next
25883f6d1a03b9037663fb1587d135020c7333235cbqhuang  availible Record. This allows all records or all records later
25983f6d1a03b9037663fb1587d135020c7333235cbqhuang  than a give MonotonicCount to be returned. If an optional FilterDriverEvent
26083f6d1a03b9037663fb1587d135020c7333235cbqhuang  is passed in with a MonotonicCout of zero return the first record
26183f6d1a03b9037663fb1587d135020c7333235cbqhuang  not yet read by the filter driver. If FilterDriverEvent is NULL and
26283f6d1a03b9037663fb1587d135020c7333235cbqhuang  MonotonicCount is zero return the first data record.
26383f6d1a03b9037663fb1587d135020c7333235cbqhuang
2642ab239290ded075c540a463815dae5e74fea52c6klu  @param This                     Pointer to the EFI_DATA_HUB_PROTOCOL instance.
2652ab239290ded075c540a463815dae5e74fea52c6klu  @param MonotonicCount           Specifies the Record to return. On input, zero means
2662ab239290ded075c540a463815dae5e74fea52c6klu                                  return the first record. On output, contains the next
2672ab239290ded075c540a463815dae5e74fea52c6klu                                  record to availible. Zero indicates no more records.
2682ab239290ded075c540a463815dae5e74fea52c6klu  @param FilterDriverEvent        If FilterDriverEvent is not passed in a MonotonicCount
2692ab239290ded075c540a463815dae5e74fea52c6klu                                  of zero, it means to return the first data record.
2702ab239290ded075c540a463815dae5e74fea52c6klu                                  If FilterDriverEvent is passed in, then a MonotonicCount
2712ab239290ded075c540a463815dae5e74fea52c6klu                                  of zero means to return the first data not yet read by
2722ab239290ded075c540a463815dae5e74fea52c6klu                                  FilterDriverEvent.
2732ab239290ded075c540a463815dae5e74fea52c6klu  @param Record                   Returns a dynamically allocated memory buffer with a data
2742ab239290ded075c540a463815dae5e74fea52c6klu                                  record that matches MonotonicCount.
2752ab239290ded075c540a463815dae5e74fea52c6klu
2762ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_SUCCESS             Data was returned in Record.
2772ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_INVALID_PARAMETER   FilterDriverEvent was passed in but does not exist.
2782ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_NOT_FOUND           MonotonicCount does not match any data record in the
2792ab239290ded075c540a463815dae5e74fea52c6klu                                  system. If a MonotonicCount of zero was passed in, then
2802ab239290ded075c540a463815dae5e74fea52c6klu                                  no data records exist in the system.
2812ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_OUT_OF_RESOURCES    Record was not returned due to lack of system resources.
28283f6d1a03b9037663fb1587d135020c7333235cbqhuang
283a73d0c743b5192b1038a24711525eed71dfa300fklu**/
284a73d0c743b5192b1038a24711525eed71dfa300fkluEFI_STATUS
285a73d0c743b5192b1038a24711525eed71dfa300fkluEFIAPI
286a73d0c743b5192b1038a24711525eed71dfa300fkluDataHubGetNextRecord (
287a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_DATA_HUB_PROTOCOL            *This,
288a73d0c743b5192b1038a24711525eed71dfa300fklu  IN OUT UINT64                       *MonotonicCount,
289a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_EVENT                        *FilterDriverEvent, OPTIONAL
290a73d0c743b5192b1038a24711525eed71dfa300fklu  OUT EFI_DATA_RECORD_HEADER          **Record
291a73d0c743b5192b1038a24711525eed71dfa300fklu  )
29283f6d1a03b9037663fb1587d135020c7333235cbqhuang{
29383f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_INSTANCE       *Private;
29483f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_FILTER_DRIVER  *FilterDriver;
29583f6d1a03b9037663fb1587d135020c7333235cbqhuang  UINT64                  ClassFilter;
29683f6d1a03b9037663fb1587d135020c7333235cbqhuang
29783f6d1a03b9037663fb1587d135020c7333235cbqhuang  Private               = DATA_HUB_INSTANCE_FROM_THIS (This);
29883f6d1a03b9037663fb1587d135020c7333235cbqhuang
29983f6d1a03b9037663fb1587d135020c7333235cbqhuang  FilterDriver          = NULL;
30083f6d1a03b9037663fb1587d135020c7333235cbqhuang  ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |
30183f6d1a03b9037663fb1587d135020c7333235cbqhuang    EFI_DATA_RECORD_CLASS_ERROR |
30283f6d1a03b9037663fb1587d135020c7333235cbqhuang    EFI_DATA_RECORD_CLASS_DATA |
30383f6d1a03b9037663fb1587d135020c7333235cbqhuang    EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
30483f6d1a03b9037663fb1587d135020c7333235cbqhuang
305d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
306d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // If FilterDriverEvent is NULL, then return the next record
307d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
308d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  if (FilterDriverEvent == NULL) {
309d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
310d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    if (*Record == NULL) {
311d2720e0ce8fc47df268f7b494469114391115ec9mdkinney      return EFI_NOT_FOUND;
31283f6d1a03b9037663fb1587d135020c7333235cbqhuang    }
313d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    return EFI_SUCCESS;
314d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  }
315d2720e0ce8fc47df268f7b494469114391115ec9mdkinney
316d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
317d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // For events the beginning is the last unread record. This info is
318d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // stored in the instance structure, so we must look up the event
319d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // to get the data.
320d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
321d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  FilterDriver = FindFilterDriverByEvent (
322d2720e0ce8fc47df268f7b494469114391115ec9mdkinney                  &Private->FilterDriverListHead,
323d2720e0ce8fc47df268f7b494469114391115ec9mdkinney                  *FilterDriverEvent
324d2720e0ce8fc47df268f7b494469114391115ec9mdkinney                  );
325d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  if (FilterDriver == NULL) {
326d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    return EFI_INVALID_PARAMETER;
327d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  }
328d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
329d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // Use the Class filter the event was created with.
330d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
331d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  ClassFilter = FilterDriver->ClassFilter;
33283f6d1a03b9037663fb1587d135020c7333235cbqhuang
333d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
334d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // Retrieve the next record or the first record.
335d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
336d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  if (*MonotonicCount != 0 || FilterDriver->GetNextMonotonicCount == 0) {
337d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
338d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    if (*Record == NULL) {
339d2720e0ce8fc47df268f7b494469114391115ec9mdkinney      return EFI_NOT_FOUND;
340d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    }
341d2720e0ce8fc47df268f7b494469114391115ec9mdkinney
342d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    if (*MonotonicCount != 0) {
34383f6d1a03b9037663fb1587d135020c7333235cbqhuang      //
344d2720e0ce8fc47df268f7b494469114391115ec9mdkinney      // If this was not the last record then update the count associated with the filter
34583f6d1a03b9037663fb1587d135020c7333235cbqhuang      //
346d2720e0ce8fc47df268f7b494469114391115ec9mdkinney      FilterDriver->GetNextMonotonicCount = *MonotonicCount;
347d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    } else {
3482ebbe08cb6f2e1a52b672c220275bcde401a4413gikidy      //
349d2720e0ce8fc47df268f7b494469114391115ec9mdkinney      // Save the MonotonicCount of the last record which has been read
3502ebbe08cb6f2e1a52b672c220275bcde401a4413gikidy      //
351d2720e0ce8fc47df268f7b494469114391115ec9mdkinney      FilterDriver->GetNextMonotonicCount = (*Record)->LogMonotonicCount;
35283f6d1a03b9037663fb1587d135020c7333235cbqhuang    }
353d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    return EFI_SUCCESS;
35483f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
355d2720e0ce8fc47df268f7b494469114391115ec9mdkinney
356d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
357d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // This is a request to read the first record that has not been read yet.
358d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // Set MonotoicCount to the last record successfuly read
359d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  //
360d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  *MonotonicCount = FilterDriver->GetNextMonotonicCount;
361d2720e0ce8fc47df268f7b494469114391115ec9mdkinney
36283f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
363d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // Retrieve the last record successfuly read again, but do not return it since
364d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  // it has already been returned before.
36583f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
36683f6d1a03b9037663fb1587d135020c7333235cbqhuang  *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
36783f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (*Record == NULL) {
36883f6d1a03b9037663fb1587d135020c7333235cbqhuang    return EFI_NOT_FOUND;
36983f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
370d2720e0ce8fc47df268f7b494469114391115ec9mdkinney
371d2720e0ce8fc47df268f7b494469114391115ec9mdkinney  if (*MonotonicCount != 0) {
37283f6d1a03b9037663fb1587d135020c7333235cbqhuang    //
373d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    // Update the count associated with the filter
37483f6d1a03b9037663fb1587d135020c7333235cbqhuang    //
375d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    FilterDriver->GetNextMonotonicCount = *MonotonicCount;
376d2720e0ce8fc47df268f7b494469114391115ec9mdkinney
377d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    //
378d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    // Retrieve the record after the last record successfuly read
379d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    //
380d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount);
381d2720e0ce8fc47df268f7b494469114391115ec9mdkinney    if (*Record == NULL) {
382d2720e0ce8fc47df268f7b494469114391115ec9mdkinney      return EFI_NOT_FOUND;
38383f6d1a03b9037663fb1587d135020c7333235cbqhuang    }
38483f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
385d2720e0ce8fc47df268f7b494469114391115ec9mdkinney
38683f6d1a03b9037663fb1587d135020c7333235cbqhuang  return EFI_SUCCESS;
38783f6d1a03b9037663fb1587d135020c7333235cbqhuang}
38883f6d1a03b9037663fb1587d135020c7333235cbqhuang
389a73d0c743b5192b1038a24711525eed71dfa300fklu/**
39083f6d1a03b9037663fb1587d135020c7333235cbqhuang  This function registers the data hub filter driver that is represented
39183f6d1a03b9037663fb1587d135020c7333235cbqhuang  by FilterEvent. Only one instance of each FilterEvent can be registered.
39283f6d1a03b9037663fb1587d135020c7333235cbqhuang  After the FilterEvent is registered, it will be signaled so it can sync
39383f6d1a03b9037663fb1587d135020c7333235cbqhuang  with data records that have been recorded prior to the FilterEvent being
39483f6d1a03b9037663fb1587d135020c7333235cbqhuang  registered.
39583f6d1a03b9037663fb1587d135020c7333235cbqhuang
3962ab239290ded075c540a463815dae5e74fea52c6klu  @param This                   Pointer to  The EFI_DATA_HUB_PROTOCOL instance.
3972ab239290ded075c540a463815dae5e74fea52c6klu  @param FilterEvent            The EFI_EVENT to signal whenever data that matches
3982ab239290ded075c540a463815dae5e74fea52c6klu                                FilterClass is logged in the system.
3992ab239290ded075c540a463815dae5e74fea52c6klu  @param FilterTpl              The maximum EFI_TPL at which FilterEvent can be
4002ab239290ded075c540a463815dae5e74fea52c6klu                                signaled. It is strongly recommended that you use the
4012ab239290ded075c540a463815dae5e74fea52c6klu                                lowest EFI_TPL possible.
4022ab239290ded075c540a463815dae5e74fea52c6klu  @param FilterClass            FilterEvent will be signaled whenever a bit in
4032ab239290ded075c540a463815dae5e74fea52c6klu                                EFI_DATA_RECORD_HEADER.DataRecordClass is also set in
4042ab239290ded075c540a463815dae5e74fea52c6klu                                FilterClass. If FilterClass is zero, no class-based
4052ab239290ded075c540a463815dae5e74fea52c6klu                                filtering will be performed.
4062ab239290ded075c540a463815dae5e74fea52c6klu  @param FilterDataRecordGuid   FilterEvent will be signaled whenever FilterDataRecordGuid
4072ab239290ded075c540a463815dae5e74fea52c6klu                                matches EFI_DATA_RECORD_HEADER.DataRecordGuid. If
4082ab239290ded075c540a463815dae5e74fea52c6klu                                FilterDataRecordGuid is NULL, then no GUID-based filtering
4092ab239290ded075c540a463815dae5e74fea52c6klu                                will be performed.
4102ab239290ded075c540a463815dae5e74fea52c6klu
4112ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_SUCCESS           The filter driver event was registered.
4122ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_ALREADY_STARTED   FilterEvent was previously registered and cannot be
4132ab239290ded075c540a463815dae5e74fea52c6klu                                registered again.
4142ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_OUT_OF_RESOURCES  The filter driver event was not registered due to lack of
4152ab239290ded075c540a463815dae5e74fea52c6klu                                system resources.
41683f6d1a03b9037663fb1587d135020c7333235cbqhuang
417a73d0c743b5192b1038a24711525eed71dfa300fklu**/
418a73d0c743b5192b1038a24711525eed71dfa300fkluEFI_STATUS
419a73d0c743b5192b1038a24711525eed71dfa300fkluEFIAPI
420a73d0c743b5192b1038a24711525eed71dfa300fkluDataHubRegisterFilterDriver (
421a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_DATA_HUB_PROTOCOL    * This,
422a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_EVENT                FilterEvent,
423a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_TPL                  FilterTpl,
424a73d0c743b5192b1038a24711525eed71dfa300fklu  IN UINT64                   FilterClass,
425a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_GUID                 * FilterDataRecordGuid OPTIONAL
426a73d0c743b5192b1038a24711525eed71dfa300fklu  )
427a73d0c743b5192b1038a24711525eed71dfa300fklu
42883f6d1a03b9037663fb1587d135020c7333235cbqhuang{
42983f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_INSTANCE       *Private;
43083f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_FILTER_DRIVER  *FilterDriver;
43183f6d1a03b9037663fb1587d135020c7333235cbqhuang
43283f6d1a03b9037663fb1587d135020c7333235cbqhuang  Private       = DATA_HUB_INSTANCE_FROM_THIS (This);
43383f6d1a03b9037663fb1587d135020c7333235cbqhuang
43483f6d1a03b9037663fb1587d135020c7333235cbqhuang  FilterDriver  = (DATA_HUB_FILTER_DRIVER *) AllocateZeroPool (sizeof (DATA_HUB_FILTER_DRIVER));
43583f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (FilterDriver == NULL) {
43683f6d1a03b9037663fb1587d135020c7333235cbqhuang    return EFI_OUT_OF_RESOURCES;
43783f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
43883f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
43983f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Initialize filter driver info
44083f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
44183f6d1a03b9037663fb1587d135020c7333235cbqhuang  FilterDriver->Signature             = EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE;
44283f6d1a03b9037663fb1587d135020c7333235cbqhuang  FilterDriver->Event                 = FilterEvent;
44383f6d1a03b9037663fb1587d135020c7333235cbqhuang  FilterDriver->Tpl                   = FilterTpl;
44483f6d1a03b9037663fb1587d135020c7333235cbqhuang  FilterDriver->GetNextMonotonicCount = 0;
44583f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (FilterClass == 0) {
44683f6d1a03b9037663fb1587d135020c7333235cbqhuang    FilterDriver->ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG |
44783f6d1a03b9037663fb1587d135020c7333235cbqhuang      EFI_DATA_RECORD_CLASS_ERROR |
44883f6d1a03b9037663fb1587d135020c7333235cbqhuang      EFI_DATA_RECORD_CLASS_DATA |
44983f6d1a03b9037663fb1587d135020c7333235cbqhuang      EFI_DATA_RECORD_CLASS_PROGRESS_CODE;
45083f6d1a03b9037663fb1587d135020c7333235cbqhuang  } else {
45183f6d1a03b9037663fb1587d135020c7333235cbqhuang    FilterDriver->ClassFilter = FilterClass;
45283f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
45383f6d1a03b9037663fb1587d135020c7333235cbqhuang
45483f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (FilterDataRecordGuid != NULL) {
45583f6d1a03b9037663fb1587d135020c7333235cbqhuang    CopyMem (&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID));
45683f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
45783f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
45883f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Search for duplicate entries
45983f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
46083f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) {
46183f6d1a03b9037663fb1587d135020c7333235cbqhuang    FreePool (FilterDriver);
46283f6d1a03b9037663fb1587d135020c7333235cbqhuang    return EFI_ALREADY_STARTED;
46383f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
46483f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
46583f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Make insertion an atomic operation with the lock.
46683f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
46783f6d1a03b9037663fb1587d135020c7333235cbqhuang  EfiAcquireLock (&Private->DataLock);
46883f6d1a03b9037663fb1587d135020c7333235cbqhuang  InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link);
46983f6d1a03b9037663fb1587d135020c7333235cbqhuang  EfiReleaseLock (&Private->DataLock);
47083f6d1a03b9037663fb1587d135020c7333235cbqhuang
47183f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
47283f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Signal the Filter driver we just loaded so they will recieve all the
47383f6d1a03b9037663fb1587d135020c7333235cbqhuang  // previous history. If we did not signal here we would have to wait until
47483f6d1a03b9037663fb1587d135020c7333235cbqhuang  // the next data was logged to get the history. In a case where no next
47583f6d1a03b9037663fb1587d135020c7333235cbqhuang  // data was logged we would never get synced up.
47683f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
47783f6d1a03b9037663fb1587d135020c7333235cbqhuang  gBS->SignalEvent (FilterEvent);
47883f6d1a03b9037663fb1587d135020c7333235cbqhuang
47983f6d1a03b9037663fb1587d135020c7333235cbqhuang  return EFI_SUCCESS;
48083f6d1a03b9037663fb1587d135020c7333235cbqhuang}
48183f6d1a03b9037663fb1587d135020c7333235cbqhuang
482a73d0c743b5192b1038a24711525eed71dfa300fklu/**
48383f6d1a03b9037663fb1587d135020c7333235cbqhuang  Remove a Filter Driver, so it no longer gets called when data
48483f6d1a03b9037663fb1587d135020c7333235cbqhuang   information is logged.
48583f6d1a03b9037663fb1587d135020c7333235cbqhuang
4862ab239290ded075c540a463815dae5e74fea52c6klu  @param This           Protocol instance structure
48783f6d1a03b9037663fb1587d135020c7333235cbqhuang
4882ab239290ded075c540a463815dae5e74fea52c6klu  @param FilterEvent    Event that represents a filter driver that is to be
4892ab239290ded075c540a463815dae5e74fea52c6klu                        Unregistered.
49083f6d1a03b9037663fb1587d135020c7333235cbqhuang
4912ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_SUCCESS   If FilterEvent was unregistered
4922ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_NOT_FOUND If FilterEvent does not exist
493a73d0c743b5192b1038a24711525eed71dfa300fklu**/
494a73d0c743b5192b1038a24711525eed71dfa300fkluEFI_STATUS
495a73d0c743b5192b1038a24711525eed71dfa300fkluEFIAPI
496a73d0c743b5192b1038a24711525eed71dfa300fkluDataHubUnregisterFilterDriver (
497a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_DATA_HUB_PROTOCOL    *This,
498a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_EVENT                FilterEvent
499a73d0c743b5192b1038a24711525eed71dfa300fklu  )
50083f6d1a03b9037663fb1587d135020c7333235cbqhuang{
50183f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_INSTANCE       *Private;
50283f6d1a03b9037663fb1587d135020c7333235cbqhuang  DATA_HUB_FILTER_DRIVER  *FilterDriver;
50383f6d1a03b9037663fb1587d135020c7333235cbqhuang
50483f6d1a03b9037663fb1587d135020c7333235cbqhuang  Private = DATA_HUB_INSTANCE_FROM_THIS (This);
50583f6d1a03b9037663fb1587d135020c7333235cbqhuang
50683f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
50783f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Search for duplicate entries
50883f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
50983f6d1a03b9037663fb1587d135020c7333235cbqhuang  FilterDriver = FindFilterDriverByEvent (
51083f6d1a03b9037663fb1587d135020c7333235cbqhuang                  &Private->FilterDriverListHead,
51183f6d1a03b9037663fb1587d135020c7333235cbqhuang                  FilterEvent
51283f6d1a03b9037663fb1587d135020c7333235cbqhuang                  );
51383f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (FilterDriver == NULL) {
51483f6d1a03b9037663fb1587d135020c7333235cbqhuang    return EFI_NOT_FOUND;
51583f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
51683f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
51783f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Make removal an atomic operation with the lock
51883f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
51983f6d1a03b9037663fb1587d135020c7333235cbqhuang  EfiAcquireLock (&Private->DataLock);
52083f6d1a03b9037663fb1587d135020c7333235cbqhuang  RemoveEntryList (&FilterDriver->Link);
52183f6d1a03b9037663fb1587d135020c7333235cbqhuang  EfiReleaseLock (&Private->DataLock);
52283f6d1a03b9037663fb1587d135020c7333235cbqhuang
52383f6d1a03b9037663fb1587d135020c7333235cbqhuang  return EFI_SUCCESS;
52483f6d1a03b9037663fb1587d135020c7333235cbqhuang}
52583f6d1a03b9037663fb1587d135020c7333235cbqhuang
52683f6d1a03b9037663fb1587d135020c7333235cbqhuang
52783f6d1a03b9037663fb1587d135020c7333235cbqhuang
528a73d0c743b5192b1038a24711525eed71dfa300fklu/**
5292ab239290ded075c540a463815dae5e74fea52c6klu  Driver's Entry point routine that install Driver to produce Data Hub protocol.
53083f6d1a03b9037663fb1587d135020c7333235cbqhuang
5312ab239290ded075c540a463815dae5e74fea52c6klu  @param ImageHandle    Module's image handle
5322ab239290ded075c540a463815dae5e74fea52c6klu  @param SystemTable    Pointer of EFI_SYSTEM_TABLE
53383f6d1a03b9037663fb1587d135020c7333235cbqhuang
5342ab239290ded075c540a463815dae5e74fea52c6klu  @retval EFI_SUCCESS   Logging Hub protocol installed
5352ab239290ded075c540a463815dae5e74fea52c6klu  @retval Other         No protocol installed, unload driver.
53683f6d1a03b9037663fb1587d135020c7333235cbqhuang
537a73d0c743b5192b1038a24711525eed71dfa300fklu**/
538a73d0c743b5192b1038a24711525eed71dfa300fkluEFI_STATUS
539a73d0c743b5192b1038a24711525eed71dfa300fkluEFIAPI
540a73d0c743b5192b1038a24711525eed71dfa300fkluDataHubInstall (
541a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_HANDLE           ImageHandle,
542a73d0c743b5192b1038a24711525eed71dfa300fklu  IN EFI_SYSTEM_TABLE     *SystemTable
543a73d0c743b5192b1038a24711525eed71dfa300fklu  )
54483f6d1a03b9037663fb1587d135020c7333235cbqhuang{
54583f6d1a03b9037663fb1587d135020c7333235cbqhuang  EFI_STATUS  Status;
54683f6d1a03b9037663fb1587d135020c7333235cbqhuang  UINT32      HighMontonicCount;
54783f6d1a03b9037663fb1587d135020c7333235cbqhuang
54883f6d1a03b9037663fb1587d135020c7333235cbqhuang  mPrivateData.Signature                      = DATA_HUB_INSTANCE_SIGNATURE;
54983f6d1a03b9037663fb1587d135020c7333235cbqhuang  mPrivateData.DataHub.LogData                = DataHubLogData;
55083f6d1a03b9037663fb1587d135020c7333235cbqhuang  mPrivateData.DataHub.GetNextRecord          = DataHubGetNextRecord;
55183f6d1a03b9037663fb1587d135020c7333235cbqhuang  mPrivateData.DataHub.RegisterFilterDriver   = DataHubRegisterFilterDriver;
55283f6d1a03b9037663fb1587d135020c7333235cbqhuang  mPrivateData.DataHub.UnregisterFilterDriver = DataHubUnregisterFilterDriver;
55383f6d1a03b9037663fb1587d135020c7333235cbqhuang
55483f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
55583f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is
5562ab239290ded075c540a463815dae5e74fea52c6klu  // required by this protocol
55783f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
55883f6d1a03b9037663fb1587d135020c7333235cbqhuang  InitializeListHead (&mPrivateData.DataListHead);
55983f6d1a03b9037663fb1587d135020c7333235cbqhuang  InitializeListHead (&mPrivateData.FilterDriverListHead);
56083f6d1a03b9037663fb1587d135020c7333235cbqhuang
561b4c900588691090ae931a630b93f5c8753677e68lgao  EfiInitializeLock (&mPrivateData.DataLock, TPL_NOTIFY);
56283f6d1a03b9037663fb1587d135020c7333235cbqhuang
56383f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
56483f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Make sure we get a bigger MTC number on every boot!
56583f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
56683f6d1a03b9037663fb1587d135020c7333235cbqhuang  Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount);
56783f6d1a03b9037663fb1587d135020c7333235cbqhuang  if (EFI_ERROR (Status)) {
56883f6d1a03b9037663fb1587d135020c7333235cbqhuang    //
56983f6d1a03b9037663fb1587d135020c7333235cbqhuang    // if system service fails pick a sane value.
57083f6d1a03b9037663fb1587d135020c7333235cbqhuang    //
57183f6d1a03b9037663fb1587d135020c7333235cbqhuang    mPrivateData.GlobalMonotonicCount = 0;
57283f6d1a03b9037663fb1587d135020c7333235cbqhuang  } else {
57383f6d1a03b9037663fb1587d135020c7333235cbqhuang    mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64) HighMontonicCount, 32);
57483f6d1a03b9037663fb1587d135020c7333235cbqhuang  }
57583f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
57683f6d1a03b9037663fb1587d135020c7333235cbqhuang  // Make a new handle and install the protocol
57783f6d1a03b9037663fb1587d135020c7333235cbqhuang  //
57883f6d1a03b9037663fb1587d135020c7333235cbqhuang  mPrivateData.Handle = NULL;
57983f6d1a03b9037663fb1587d135020c7333235cbqhuang  Status = gBS->InstallProtocolInterface (
58083f6d1a03b9037663fb1587d135020c7333235cbqhuang                  &mPrivateData.Handle,
58183f6d1a03b9037663fb1587d135020c7333235cbqhuang                  &gEfiDataHubProtocolGuid,
58283f6d1a03b9037663fb1587d135020c7333235cbqhuang                  EFI_NATIVE_INTERFACE,
58383f6d1a03b9037663fb1587d135020c7333235cbqhuang                  &mPrivateData.DataHub
58483f6d1a03b9037663fb1587d135020c7333235cbqhuang                  );
58583f6d1a03b9037663fb1587d135020c7333235cbqhuang  return Status;
58683f6d1a03b9037663fb1587d135020c7333235cbqhuang}
587a73d0c743b5192b1038a24711525eed71dfa300fklu
588