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
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
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