This driver is responsible for the registration of child drivers\r
and the abstraction of the QNC SMI sources.\r
\r
-Copyright (c) 2013-2015 Intel Corporation.\r
+Copyright (c) 2013-2016 Intel Corporation.\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
// Gather information about the registration request\r
//\r
Record->Callback = DispatchFunction;\r
- Record->ChildContext = *RegisterContext;\r
+ Record->CallbackContext = RegisterContext;\r
+ CopyMem (&Record->ChildContext, RegisterContext, sizeof (QNC_SMM_CONTEXT));\r
\r
Qualified = QUALIFIED_PROTOCOL_FROM_GENERIC (This);\r
\r
//\r
// Update ChildContext again as SwSmiInputValue has been changed\r
//\r
- Record->ChildContext = *RegisterContext;\r
+ CopyMem (&Record->ChildContext, RegisterContext, sizeof (QNC_SMM_CONTEXT));\r
}\r
\r
//\r
BOOLEAN ChildWasDispatched;\r
\r
DATABASE_RECORD *RecordInDb;\r
+ DATABASE_RECORD ActiveRecordInDb;\r
LIST_ENTRY *LinkInDb;\r
DATABASE_RECORD *RecordToExhaust;\r
LIST_ENTRY *LinkToExhaust;\r
Status = EFI_WARN_INTERRUPT_SOURCE_PENDING;\r
ChildWasDispatched = FALSE;\r
\r
+ //\r
+ // Mark all child handlers as not processed\r
+ //\r
+ LinkInDb = GetFirstNode (&mPrivateData.CallbackDataBase);\r
+ while (!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) {\r
+ RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+ RecordInDb->Processed = FALSE;\r
+ LinkInDb = GetNextNode (&mPrivateData.CallbackDataBase, LinkInDb);\r
+ }\r
+\r
//\r
// Preserve Index registers\r
//\r
\r
while ((!IsNull (&mPrivateData.CallbackDataBase, LinkInDb)) && (ResetListSearch == FALSE)) {\r
RecordInDb = DATABASE_RECORD_FROM_LINK (LinkInDb);\r
+ //\r
+ // Make a copy of the record that contains an active SMI source,\r
+ // because un-register maybe invoked in callback function and\r
+ // RecordInDb maybe released\r
+ //\r
+ CopyMem (&ActiveRecordInDb, RecordInDb, sizeof (ActiveRecordInDb));\r
\r
//\r
// look for the first active source\r
//\r
while (!IsNull (&mPrivateData.CallbackDataBase, LinkToExhaust)) {\r
RecordToExhaust = DATABASE_RECORD_FROM_LINK (LinkToExhaust);\r
+ LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, LinkToExhaust);\r
+ if (RecordToExhaust->Processed) {\r
+ //\r
+ // Record has already been processed. Continue with next child handler.\r
+ //\r
+ continue;\r
+ }\r
\r
if (CompareSources (&RecordToExhaust->SrcDesc, &ActiveSource)) {\r
//\r
// it supplied in registration. Simply pass back what it gave us.\r
//\r
ASSERT (RecordToExhaust->Callback != NULL);\r
- Context = RecordToExhaust->ChildContext;\r
ContextsMatch = TRUE;\r
}\r
\r
+ //\r
+ // Mark this child handler so it will not be processed again\r
+ //\r
+ RecordToExhaust->Processed = TRUE;\r
+\r
if (ContextsMatch) {\r
\r
if (RecordToExhaust->BufferSize != 0) {\r
\r
RecordToExhaust->Callback (\r
(EFI_HANDLE) & RecordToExhaust->Link,\r
- &Context,\r
+ RecordToExhaust->CallbackContext,\r
CommunicationBuffer,\r
&BufferSize\r
);\r
SxChildWasDispatched = TRUE;\r
}\r
}\r
+ //\r
+ // Can not use RecordInDb after this point because Callback may have unregistered RecordInDb\r
+ // Restart processing of SMI handlers from the begining of the linked list because the\r
+ // state of the linked listed may have been modified due to unregister actions in the Callback.\r
+ //\r
+ LinkToExhaust = GetFirstNode (&mPrivateData.CallbackDataBase);\r
}\r
- //\r
- // Get next record in DB\r
- //\r
- LinkToExhaust = GetNextNode (&mPrivateData.CallbackDataBase, &RecordToExhaust->Link);\r
}\r
\r
if (RecordInDb->ClearSource == NULL) {\r
//\r
// This source requires special handling to clear\r
//\r
- RecordInDb->ClearSource (&ActiveSource);\r
+ ActiveRecordInDb.ClearSource (&ActiveSource);\r
}\r
\r
if (ChildWasDispatched) {\r